1use std::cell::Cell;
2
3use gapbuf::{GapBuffer, gap_buffer};
4
5pub use self::cursor::{Cursor, VPoint};
6use crate::{
7 add_shifts, merging_range_by_guess_and_lazy_shift,
8 text::{Change, Point},
9};
10
11#[derive(Clone)]
12pub struct Cursors {
13 buf: GapBuffer<Cursor>,
14 main_i: usize,
15 shift_state: Cell<(usize, [i32; 3])>,
16}
17
18impl Cursors {
19 pub fn new() -> Self {
21 Self {
22 buf: gap_buffer![Cursor::default()],
23 main_i: 0,
24 shift_state: Cell::new((0, [0; 3])),
25 }
26 }
27
28 pub(crate) fn new_with_main(main: Cursor) -> Self {
30 Self {
31 buf: gap_buffer![main],
32 main_i: 0,
33 shift_state: Cell::new((0, [0; 3])),
34 }
35 }
36
37 pub fn insert(&mut self, guess_i: usize, cursor: Cursor, was_main: bool) -> ([usize; 2], bool) {
38 let (sh_from, shift) = self.shift_state.take();
39 let sh_from = sh_from.min(self.len());
40
41 let c_range = merging_range_by_guess_and_lazy_shift(
43 (&self.buf, self.buf.len()),
44 (guess_i, [cursor.start(), cursor.end_excl()]),
45 (sh_from, shift, [0; 3], Point::shift_by),
46 (Cursor::start, Cursor::end_excl),
47 );
48
49 if sh_from < c_range.end && shift != [0; 3] {
51 for cursor in self.buf.range(sh_from..c_range.end).into_iter() {
52 cursor.shift_by(shift);
53 }
54 }
55
56 let (caret, anchor, last_cursor_overhangs) = {
59 let mut c_range = c_range.clone();
60 let first = c_range.next().and_then(|i| self.get(i));
61 let last = c_range.last().and_then(|i| self.get(i)).or(first);
62 let start = first
63 .map(|first| first.lazy_v_start().min(cursor.lazy_v_start()))
64 .unwrap_or(cursor.lazy_v_start());
65 let (end, last_cursor_overhangs) = if let Some(last) = last
66 && last.lazy_v_end() >= cursor.lazy_v_end()
67 {
68 (last.lazy_v_end(), true)
69 } else {
70 (cursor.lazy_v_end(), false)
71 };
72
73 if let Some(anchor) = cursor.anchor() {
74 match cursor.caret() < anchor {
75 true => (start, Some(end), last_cursor_overhangs),
76 false => (end, Some(start), last_cursor_overhangs),
77 }
78 } else {
79 (end, (start != end).then_some(start), last_cursor_overhangs)
80 }
81 };
82
83 let cursor = Cursor::from_v(caret, anchor, cursor.change_i);
84 self.buf.splice(c_range.clone(), [cursor]);
85
86 if was_main {
87 self.main_i = c_range.start;
88 } else if self.main_i >= c_range.start {
89 self.main_i = (self.main_i + 1 - c_range.clone().count()).max(c_range.start)
90 }
91
92 let cursors_taken = c_range.clone().count();
94 let new_sh_from = sh_from.saturating_sub(cursors_taken).max(c_range.start) + 1;
95 if new_sh_from < self.buf.len() {
96 self.shift_state.set((new_sh_from, shift));
97 }
98
99 ([c_range.start, cursors_taken], last_cursor_overhangs)
100 }
101
102 pub(crate) fn apply_change(&mut self, guess_i: usize, change: Change<&str>) -> usize {
104 let (sh_from, shift) = self.shift_state.take();
105 let sh_from = sh_from.min(self.len());
106
107 let c_range = merging_range_by_guess_and_lazy_shift(
109 (&self.buf, self.buf.len()),
110 (guess_i, [change.start(), change.taken_end()]),
111 (sh_from, shift, [0; 3], Point::shift_by),
112 (Cursor::start, Cursor::end_excl),
113 );
114
115 if c_range.end > sh_from && shift != [0; 3] {
119 for cursor in self.buf.range(sh_from..c_range.end).into_iter() {
120 cursor.shift_by(shift);
121 }
122 }
123 let range = c_range.start..c_range.end.max(sh_from);
124 for cursor in self.buf.range(range).into_iter() {
125 cursor.shift_by_change(change);
126 }
127
128 let (cursors_taken, cursors_added) = {
129 let mut cursors_taken = self.buf.splice(c_range.clone(), []);
130 if let Some(first) = cursors_taken.next() {
131 let last = cursors_taken.next_back().unwrap_or(first.clone());
132 let (start, end) = (first.start(), last.end_excl());
133 let merged = Cursor::new(start, (start < end).then_some(end));
134 drop(cursors_taken);
135 self.buf.insert(c_range.start, merged);
136
137 (c_range.len(), 1)
138 } else {
139 (0, 0)
140 }
141 };
142
143 let new_sh_from = sh_from.saturating_sub(cursors_taken).max(c_range.start) + cursors_added;
144 if new_sh_from < self.buf.len() {
145 self.shift_state
146 .set((new_sh_from, add_shifts(shift, change.shift())));
147 }
148
149 cursors_taken - cursors_added
150 }
151
152 pub fn set_main(&mut self, new: usize) {
153 self.main_i = new.min(self.buf.len().saturating_sub(1));
154 }
155
156 pub fn rotate_main(&mut self, amount: i32) {
157 self.main_i = (self.main_i as i32 + amount).rem_euclid(self.buf.len() as i32) as usize
158 }
159
160 pub fn remove_extras(&mut self) {
161 if !self.is_empty() {
162 let cursor = self.buf.remove(self.main_i);
163 let (sh_from, shift) = self.shift_state.take();
164 if sh_from <= self.main_i {
165 cursor.shift_by(shift);
166 }
167 self.buf = gap_buffer![cursor];
168 }
169 self.main_i = 0;
170 }
171
172 pub fn get_main(&self) -> Option<&Cursor> {
173 self.get(self.main_i)
174 }
175
176 pub fn get(&self, i: usize) -> Option<&Cursor> {
177 if i >= self.len() {
178 return None;
179 }
180 let (sh_from, shift) = self.shift_state.get();
181 if i >= sh_from && shift != [0; 3] {
182 for cursor in self.buf.range(sh_from..i + 1).iter() {
183 cursor.shift_by(shift);
184 }
185 if i + 1 < self.buf.len() {
186 self.shift_state.set((i + 1, shift));
187 } else {
188 self.shift_state.take();
189 }
190 }
191
192 self.buf.get(i)
193 }
194
195 pub fn iter(&self) -> impl Iterator<Item = (&Cursor, bool)> {
196 let (sh_from, shift) = self.shift_state.take();
199 if shift != [0; 3] {
200 for cursor in self.buf.range(sh_from..).iter() {
201 cursor.shift_by(shift);
202 }
203 }
204 self.buf
205 .iter()
206 .enumerate()
207 .map(move |(i, cursor)| (cursor, i == self.main_i))
208 }
209
210 pub fn main_index(&self) -> usize {
211 self.main_i
212 }
213
214 pub fn len(&self) -> usize {
215 self.buf.len()
216 }
217
218 #[must_use]
219 pub fn is_empty(&self) -> bool {
220 self.len() == 0
221 }
222
223 pub fn clear(&mut self) {
224 self.buf = GapBuffer::new();
225 self.shift_state.take();
226 }
227
228 pub fn reset(&mut self) {
229 self.remove_extras();
230 self.buf[self.main_i] = Cursor::default();
231 }
232
233 pub(super) fn remove(&mut self, i: usize) -> Option<(Cursor, bool)> {
234 if i >= self.buf.len() {
235 return None;
236 }
237 let (sh_from, shift) = self.shift_state.get();
238
239 if i >= sh_from && shift != [0; 3] {
240 for cursor in self.buf.range(sh_from..i + 1).iter() {
241 cursor.shift_by(shift);
242 }
243 if i + 1 < self.buf.len() {
244 self.shift_state.set((i, shift));
246 } else {
247 self.shift_state.take();
248 }
249 } else if i < sh_from {
250 self.shift_state.set((sh_from - 1, shift));
253 }
254
255 let was_main = self.main_i == i;
256 if self.main_i >= i {
257 self.main_i = self.main_i.saturating_sub(1);
258 }
259 Some((self.buf.remove(i), was_main))
260 }
261
262 pub(super) fn populate(&mut self) {
263 if self.buf.is_empty() {
264 self.main_i = 0;
265 self.buf = gap_buffer![Cursor::default()];
266 }
267 }
268}
269
270impl Default for Cursors {
271 fn default() -> Self {
272 Self::new()
273 }
274}
275
276mod cursor {
277 use std::{cell::Cell, cmp::Ordering, ops::Range};
278
279 use bincode::{Decode, Encode};
280
281 use crate::{
282 cfg::PrintCfg,
283 text::{Change, Point, Text},
284 ui::{Area, Caret},
285 };
286
287 #[derive(Default, Clone, Encode, Decode)]
290 pub struct Cursor {
291 caret: Cell<LazyVPoint>,
292 anchor: Cell<Option<LazyVPoint>>,
293 pub(in crate::mode::helper) change_i: Option<u32>,
294 }
295
296 impl Cursor {
297 pub(crate) fn new(caret: Point, anchor: Option<Point>) -> Self {
299 Self {
300 caret: Cell::new(LazyVPoint::Unknown(caret)),
301 anchor: Cell::new(anchor.map(LazyVPoint::Unknown)),
302 change_i: None,
303 }
304 }
305
306 pub(super) fn from_v(
307 caret: LazyVPoint,
308 anchor: Option<LazyVPoint>,
309 change_i: Option<u32>,
310 ) -> Self {
311 Self {
312 caret: Cell::new(caret),
313 anchor: Cell::new(anchor),
314 change_i,
315 }
316 }
317
318 pub fn move_to(&mut self, p: Point, text: &Text) {
320 if p == self.caret() {
321 return;
322 }
323 let p = text.point_at(p.byte().min(text.last_point().unwrap().byte()));
324 *self.caret.get_mut() = LazyVPoint::Unknown(p);
325 }
326
327 pub fn move_hor(&mut self, by: i32, text: &Text) -> i32 {
331 let by = by as isize;
332 let (Some(last), false) = (text.last_point(), by == 0) else {
333 return 0;
334 };
335 let target = self.caret.get().point().char().saturating_add_signed(by);
336
337 let p = if target == 0 {
338 Point::default()
339 } else if target >= last.char() {
340 last
341 } else if by.abs() < 500 {
342 if by > 0 {
343 let (point, _) = text
344 .chars_fwd(self.caret())
345 .take(by as usize + 1)
346 .last()
347 .unwrap();
348 point
349 } else {
350 let (point, _) = text
351 .chars_rev(self.caret())
352 .take(by.unsigned_abs())
353 .last()
354 .unwrap();
355 point
356 }
357 } else {
358 text.point_at_char(target)
359 };
360
361 let moved = p.char() as i32 - self.caret.get().point().char() as i32;
362 *self.caret.get_mut() = LazyVPoint::Unknown(p);
363 moved
364 }
365
366 pub fn move_ver(&mut self, by: i32, text: &Text, area: &impl Area, cfg: PrintCfg) -> i32 {
370 let by = by as isize;
371 let (Some(last), false) = (text.last_point(), by == 0) else {
372 return 0;
373 };
374
375 let (vp, moved) = {
376 let vp = self.caret.get().calculate(text, area, cfg);
377 let line_start = {
378 let target = self.caret.get().point().line().saturating_add_signed(by);
379 text.point_at_line(target.min(last.line()))
380 };
381
382 let mut wraps = 0;
383 let mut vcol = 0;
384
385 let (wcol, p) = area
386 .print_iter(text.iter_fwd(line_start), cfg.new_line_as('\n'))
387 .find_map(|(Caret { len, x, wrap }, item)| {
388 wraps += wrap as usize;
389 if let Some((p, char)) = item.as_real_char() {
390 if vcol + len as u16 > vp.dvcol || char == '\n' {
391 return Some((x as u16, p));
392 }
393 }
394 vcol += len as u16;
395 None
396 })
397 .unwrap_or((0, last));
398
399 let moved = p.line() as i32 - vp.p.line() as i32;
400 let vp = vp.known(p, (p.char() - line_start.char()) as u16, vcol, wcol);
401 (vp, moved)
402 };
403
404 *self.caret.get_mut() = LazyVPoint::Known(vp);
405 moved
406 }
407
408 pub fn move_ver_wrapped(
412 &mut self,
413 by: i32,
414 text: &Text,
415 area: &impl Area,
416 cfg: PrintCfg,
417 ) -> i32 {
418 if text.last_point().is_none() || by == 0 {
419 return 0;
420 };
421 let vp = self.caret.get().calculate(text, area, cfg);
422
423 let mut wraps = 0;
424
425 *self.caret.get_mut() = LazyVPoint::Known(if by > 0 {
426 let line_start = text.point_at_line(vp.p.line());
427 let mut vcol = vp.vcol;
428 let mut last = (vp.vcol, vp.wcol, vp.p);
429 let mut last_valid = (vp.vcol, vp.wcol, vp.p);
430
431 let (vcol, wcol, p) = area
432 .print_iter(text.iter_fwd(line_start), cfg.new_line_as('\n'))
433 .skip_while(|(_, item)| item.byte() <= self.byte())
434 .find_map(|(Caret { x, len, wrap }, item)| {
435 wraps += wrap as i32;
436 if let Some((p, char)) = item.as_real_char() {
437 if (x..x + len).contains(&(vp.dwcol as u32)) || char == '\n' {
438 last_valid = (vcol, x as u16, p);
439 if wraps == by {
440 return Some((vcol, x as u16, p));
441 }
442 } else if wraps > by {
443 return Some(last);
444 }
445 last = (vcol, x as u16, p);
446 }
447 vcol += len as u16;
448 None
449 })
450 .unwrap_or(last_valid);
451 vp.known(p, (p.char() - line_start.char()) as u16, vcol, wcol)
452 } else {
453 let end_points = text.points_after(vp.p).unwrap();
454 let mut just_wrapped = false;
455 let mut last_valid = (vp.wcol, vp.p);
456
457 let mut iter =
458 area.rev_print_iter(text.iter_rev(end_points), cfg.new_line_as('\n'));
459 let wcol_and_p = iter.find_map(|(Caret { x, len, wrap }, item)| {
460 if let Some((p, _)) = item.as_real_char() {
461 if (x..x + len).contains(&(vp.dwcol as u32))
462 || (just_wrapped && x + len < vp.dwcol as u32)
463 {
464 last_valid = (x as u16, p);
465 if wraps == by {
466 return Some((x as u16, p));
467 }
468 }
469 just_wrapped = false;
470 }
471 wraps -= wrap as i32;
472 just_wrapped |= wrap;
473 None
474 });
475
476 if let Some((wcol, p)) = wcol_and_p {
477 let (ccol, vcol) = iter
478 .take_while(|(_, item)| item.as_real_char().is_none_or(|(_, c)| c != '\n'))
479 .fold((0, 0), |(ccol, vcol), (caret, item)| {
480 (ccol + item.is_real() as u16, vcol + caret.len as u16)
481 });
482 vp.known(p, ccol, vcol, wcol)
483 } else {
484 let (wcol, p) = last_valid;
485 let (ccol, vcol) = area
486 .rev_print_iter(text.iter_rev(p), cfg.new_line_as('\n'))
487 .take_while(|(_, item)| item.as_real_char().is_none_or(|(_, c)| c != '\n'))
488 .fold((0, 0), |(ccol, vcol), (caret, item)| {
489 (ccol + item.is_real() as u16, vcol + caret.len as u16)
490 });
491 vp.known(p, ccol, vcol, wcol)
492 }
493 });
494
495 wraps
496 }
497
498 pub(crate) fn shift_by_change(&self, change: Change<&str>) {
499 let (shift, taken) = (change.shift(), change.taken_end());
500 if self.caret() >= change.start() {
501 let shifted_caret = self.caret().max(taken).shift_by(shift);
502 self.caret.set(LazyVPoint::Unknown(shifted_caret));
503 }
504 if let Some(anchor) = self.anchor.get()
505 && anchor.point() >= change.start()
506 {
507 let shifted_anchor = anchor.point().max(taken).shift_by(shift);
508 self.anchor.set(Some(LazyVPoint::Unknown(shifted_anchor)));
509 }
510 }
511
512 pub(crate) fn shift_by(&self, shift: [i32; 3]) {
515 let shifted_caret = self.caret().shift_by(shift);
516 self.caret.set(LazyVPoint::Unknown(shifted_caret));
517 if let Some(anchor) = self.anchor.get() {
518 let shifted_anchor = anchor.point().shift_by(shift);
519 self.anchor.set(Some(LazyVPoint::Unknown(shifted_anchor)));
520 }
521 }
522
523 pub fn set_anchor(&mut self) {
529 *self.anchor.get_mut() = Some(self.caret.get())
530 }
531
532 pub fn unset_anchor(&mut self) -> Option<Point> {
537 self.anchor.take().map(|a| a.point())
538 }
539
540 pub fn swap_ends(&mut self) {
542 if let Some(anchor) = self.anchor.get_mut() {
543 std::mem::swap(self.caret.get_mut(), anchor);
544 }
545 }
546
547 pub fn caret(&self) -> Point {
549 self.caret.get().point()
550 }
551
552 pub fn anchor(&self) -> Option<Point> {
553 self.anchor.get().map(|a| a.point())
554 }
555
556 pub fn byte(&self) -> usize {
559 self.caret.get().point().byte()
560 }
561
562 pub fn char(&self) -> usize {
565 self.caret.get().point().char()
566 }
567
568 pub fn line(&self) -> usize {
570 self.caret.get().point().line()
571 }
572
573 pub fn range(&self, text: &Text) -> Range<usize> {
586 let [start, end] = self.point_range(text);
587 start.byte()..end.byte()
588 }
589
590 pub fn start(&self) -> Point {
592 if let Some(anchor) = self.anchor.get() {
593 anchor.point().min(self.caret.get().point())
594 } else {
595 self.caret.get().point()
596 }
597 }
598
599 pub fn end(&self, text: &Text) -> Point {
601 let raw = self.end_excl();
602 raw.fwd(text.char_at(raw).unwrap())
603 }
604
605 pub(crate) fn end_excl(&self) -> Point {
606 if let Some(anchor) = self.anchor.get() {
607 anchor.point().max(self.caret.get().point())
608 } else {
609 self.caret.get().point()
610 }
611 }
612
613 pub(crate) fn tag_points(&self, text: &Text) -> (Point, Option<[Point; 2]>) {
614 let caret = self.caret();
615 if let Some(anchor) = self.anchor() {
616 match anchor.cmp(&caret) {
617 Ordering::Less => (caret, Some([anchor, caret])),
618 Ordering::Equal => (caret, None),
619 Ordering::Greater => {
620 let end = anchor.fwd(text.char_at(anchor).unwrap());
621 (caret, Some([caret, end]))
622 }
623 }
624 } else {
625 (caret, None)
626 }
627 }
628
629 pub fn point_range(&self, text: &Text) -> [Point; 2] {
636 [self.start(), self.end(text)]
637 }
638
639 pub fn set_desired_cols(&mut self, v: usize, w: usize) {
642 let (v, w) = (v as u16, w as u16);
643 match self.caret.get_mut() {
644 LazyVPoint::Known(vp) => {
645 vp.dvcol = v;
646 vp.dwcol = w;
647 }
648 LazyVPoint::Unknown(p) => {
649 *self.caret.get_mut() = LazyVPoint::Desired { p: *p, dvcol: v, dwcol: w }
650 }
651 LazyVPoint::Desired { dvcol, dwcol, .. } => (*dvcol, *dwcol) = (v, w),
652 }
653 }
654
655 pub fn v_caret(&self, text: &Text, area: &impl Area, cfg: PrintCfg) -> VPoint {
656 let vp = self.caret.get().calculate(text, area, cfg);
657 self.caret.set(LazyVPoint::Known(vp));
658 vp
659 }
660
661 pub fn v_anchor(&self, text: &Text, area: &impl Area, cfg: PrintCfg) -> Option<VPoint> {
662 self.anchor.get().map(|anchor| {
663 let vp = anchor.calculate(text, area, cfg);
664 self.anchor.set(Some(LazyVPoint::Known(vp)));
665 vp
666 })
667 }
668
669 pub fn v_range(&self, text: &Text, area: &impl Area, cfg: PrintCfg) -> [VPoint; 2] {
670 let v_caret = self.v_caret(text, area, cfg);
671 let v_anchor = self.v_anchor(text, area, cfg).unwrap_or(v_caret);
672 [v_caret.min(v_anchor), v_caret.max(v_anchor)]
673 }
674
675 pub(super) fn lazy_v_start(&self) -> LazyVPoint {
676 match self.anchor.get() {
677 Some(anchor) => self.caret.get().min(anchor),
678 None => self.caret.get(),
679 }
680 }
681
682 pub(super) fn lazy_v_end(&self) -> LazyVPoint {
683 match self.anchor.get() {
684 Some(anchor) => self.caret.get().max(anchor),
685 None => self.caret.get(),
686 }
687 }
688 }
689
690 #[derive(Clone, Copy, Eq, Encode, Decode)]
691 pub(super) enum LazyVPoint {
692 Known(VPoint),
693 Unknown(Point),
694 Desired { p: Point, dvcol: u16, dwcol: u16 },
695 }
696
697 impl LazyVPoint {
698 fn point(self) -> Point {
699 match self {
700 LazyVPoint::Known(vp) => vp.p,
701 LazyVPoint::Unknown(p) => p,
702 LazyVPoint::Desired { p, .. } => p,
703 }
704 }
705
706 fn calculate(self, text: &Text, area: &impl Area, cfg: PrintCfg) -> VPoint {
707 match self {
708 Self::Known(vp) => vp,
709 Self::Unknown(p) => VPoint::new(p, text, area, cfg),
710 Self::Desired { p, dvcol, dwcol } => {
711 let mut vp = VPoint::new(p, text, area, cfg);
712 vp.dvcol = dvcol;
713 vp.dwcol = dwcol;
714 vp
715 }
716 }
717 }
718 }
719
720 impl Default for LazyVPoint {
721 fn default() -> Self {
722 Self::Desired { p: Point::default(), dvcol: 0, dwcol: 0 }
723 }
724 }
725
726 impl PartialOrd for LazyVPoint {
727 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
728 Some(self.point().cmp(&other.point()))
729 }
730 }
731
732 impl Ord for LazyVPoint {
733 fn cmp(&self, other: &Self) -> Ordering {
734 self.partial_cmp(other).unwrap()
735 }
736 }
737
738 impl PartialEq for LazyVPoint {
739 fn eq(&self, other: &Self) -> bool {
740 self.point() == other.point()
741 }
742 }
743
744 #[derive(Clone, Copy, Debug, Eq, Encode, Decode)]
745 pub struct VPoint {
746 p: Point,
747 ccol: u16,
749 vcol: u16,
750 dvcol: u16,
751 wcol: u16,
752 dwcol: u16,
753 }
754
755 impl VPoint {
756 fn new(p: Point, text: &Text, area: &impl Area, cfg: PrintCfg) -> Self {
757 let [start, _] = text.points_of_line(p.line());
758
759 let mut vcol = 0;
760
761 let wcol = area
762 .print_iter(text.iter_fwd(text.visual_line_start(start)), cfg)
763 .find_map(|(caret, item)| {
764 if let Some((lhs, _)) = item.as_real_char()
765 && lhs == p
766 {
767 return Some(caret.x as u16);
768 }
769 vcol += caret.len as u16;
770 None
771 })
772 .unwrap_or(0);
773
774 Self {
775 p,
776 ccol: (p.char() - start.char()) as u16,
777 vcol,
778 dvcol: vcol,
779 wcol,
780 dwcol: wcol,
781 }
782 }
783
784 fn known(self, p: Point, ccol: u16, vcol: u16, wcol: u16) -> Self {
785 Self { p, ccol, vcol, wcol, ..self }
786 }
787
788 pub fn byte(&self) -> usize {
790 self.p.byte()
791 }
792
793 pub fn char(&self) -> usize {
795 self.p.char()
796 }
797
798 pub fn line(&self) -> usize {
800 self.p.line()
801 }
802
803 pub fn char_col(&self) -> usize {
805 self.ccol as usize
806 }
807
808 pub fn visual_col(&self) -> usize {
810 self.vcol as usize
811 }
812
813 pub fn desired_visual_col(&self) -> usize {
815 self.dvcol as usize
816 }
817
818 pub fn wrapped_col(&self) -> usize {
820 self.wcol as usize
821 }
822
823 pub fn desired_wrapped_col(&self) -> usize {
825 self.dwcol as usize
826 }
827 }
828
829 impl PartialOrd for VPoint {
830 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
831 Some(self.p.cmp(&other.p))
832 }
833 }
834
835 impl Ord for VPoint {
836 fn cmp(&self, other: &Self) -> Ordering {
837 self.partial_cmp(other).unwrap()
838 }
839 }
840
841 impl PartialEq for VPoint {
842 fn eq(&self, other: &Self) -> bool {
843 self.p == other.p
844 }
845 }
846
847 impl std::fmt::Debug for Cursor {
848 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
849 f.debug_struct("Cursor")
850 .field("caret", &self.caret.get())
851 .field("anchor", &self.anchor.get())
852 .field("change_i", &self.change_i)
853 .finish()
854 }
855 }
856
857 impl std::fmt::Debug for LazyVPoint {
858 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
859 match self {
860 Self::Known(vp) => write!(f, "Known({:?})", vp.p),
861 Self::Unknown(p) => write!(f, "Unknown({p:?}"),
862 Self::Desired { p, .. } => write!(f, "Desired({p:?})"),
863 }
864 }
865 }
866}
867
868impl std::fmt::Debug for Cursors {
869 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
870 struct DebugShiftState((usize, [i32; 3]));
871 impl std::fmt::Debug for DebugShiftState {
872 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
873 write!(f, "{:?}", self.0)
874 }
875 }
876
877 f.debug_struct("Cursors")
878 .field("buf", &self.buf)
879 .field("main_i", &self.main_i)
880 .field("shift_sate", &DebugShiftState(self.shift_state.get()))
881 .finish()
882 }
883}