1use crate::{Cursor, TextError, TextPosition};
2use ropey::iter::Chunks;
3use ropey::RopeSlice;
4use std::borrow::Cow;
5use std::cmp;
6use std::ops::Range;
7use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete};
8
9#[derive(Debug, PartialEq)]
11pub struct Grapheme<'a> {
12 grapheme: Cow<'a, str>,
14 text_bytes: Range<usize>,
16}
17
18impl<R: AsRef<str>> PartialEq<R> for Grapheme<'_> {
19 fn eq(&self, other: &R) -> bool {
20 self.grapheme.as_ref() == other.as_ref()
21 }
22}
23
24impl<'a> Grapheme<'a> {
25 pub fn new(grapheme: Cow<'a, str>, text_bytes: Range<usize>) -> Self {
26 Self {
27 grapheme,
28 text_bytes,
29 }
30 }
31
32 pub fn is_whitespace(&self) -> bool {
34 self.grapheme
35 .chars()
36 .next()
37 .map(|v| v.is_whitespace())
38 .unwrap_or(false)
39 }
40
41 pub fn is_line_break(&self) -> bool {
43 self.grapheme == "\n" || self.grapheme == "\r\n"
44 }
45
46 pub fn grapheme(&'a self) -> &'a str {
48 self.grapheme.as_ref()
49 }
50
51 pub fn text_bytes(&self) -> Range<usize> {
53 self.text_bytes.clone()
54 }
55}
56
57#[derive(Debug)]
59pub struct Glyph<'a> {
60 glyph: Cow<'a, str>,
62 text_bytes: Range<usize>,
64 screen_pos: (u16, u16),
67 screen_width: u16,
69 pos: TextPosition,
71}
72
73impl<'a> Glyph<'a> {
74 pub fn new(
75 glyph: Cow<'a, str>,
76 text_bytes: Range<usize>,
77 screen_pos: (u16, u16),
78 screen_width: u16,
79 pos: TextPosition,
80 ) -> Self {
81 Self {
82 glyph,
83 text_bytes,
84 screen_pos,
85 screen_width,
86 pos,
87 }
88 }
89
90 pub fn glyph(&'a self) -> &'a str {
92 self.glyph.as_ref()
93 }
94
95 pub fn text_bytes(&self) -> Range<usize> {
97 self.text_bytes.clone()
98 }
99
100 pub fn pos(&self) -> TextPosition {
102 self.pos
103 }
104
105 pub fn screen_pos(&self) -> (u16, u16) {
107 self.screen_pos
108 }
109
110 pub fn screen_width(&self) -> u16 {
112 self.screen_width
113 }
114}
115
116#[derive(Debug)]
118pub(crate) struct StrGraphemes<'a> {
119 text_offset: usize,
120 text: &'a str,
121 cursor: GraphemeCursor,
122}
123
124impl<'a> StrGraphemes<'a> {
125 pub(crate) fn new(slice_offset: usize, slice: &'a str) -> Self {
131 Self {
132 text_offset: slice_offset,
133 text: slice,
134 cursor: GraphemeCursor::new(0, slice.len(), true),
135 }
136 }
137
138 pub(crate) fn new_offset(slice_offset: usize, slice: &'a str, offset: usize) -> Self {
145 Self {
146 text_offset: slice_offset,
147 text: slice,
148 cursor: GraphemeCursor::new(offset, slice.len(), true),
149 }
150 }
151}
152
153impl Cursor for StrGraphemes<'_> {
154 fn prev(&mut self) -> Option<Self::Item> {
155 let start = self.cursor.cur_cursor();
156 let prev = self.cursor.prev_boundary(self.text, 0).unwrap()?;
157 Some(Grapheme {
158 grapheme: Cow::Borrowed(&self.text[prev..start]),
159 text_bytes: self.text_offset + prev..self.text_offset + start,
160 })
161 }
162
163 fn rev_cursor(self) -> impl Cursor<Item = Self::Item> {
164 RevStrGraphemes { it: self }
165 }
166
167 fn text_offset(&self) -> usize {
168 self.text_offset + self.cursor.cur_cursor()
169 }
170}
171
172impl<'a> Iterator for StrGraphemes<'a> {
173 type Item = Grapheme<'a>;
174
175 #[inline]
176 fn next(&mut self) -> Option<Grapheme<'a>> {
177 let start = self.cursor.cur_cursor();
178 let next = self.cursor.next_boundary(self.text, 0).unwrap()?;
179 Some(Grapheme {
180 grapheme: Cow::Borrowed(&self.text[start..next]),
181 text_bytes: self.text_offset + start..self.text_offset + next,
182 })
183 }
184
185 #[inline]
186 fn size_hint(&self) -> (usize, Option<usize>) {
187 let slen = self.text.len() - self.cursor.cur_cursor();
188 (cmp::min(slen, 1), Some(slen))
189 }
190}
191
192#[derive(Debug)]
193pub(crate) struct RevStrGraphemes<'a> {
194 it: StrGraphemes<'a>,
195}
196
197impl<'a> Iterator for RevStrGraphemes<'a> {
198 type Item = Grapheme<'a>;
199
200 #[inline]
201 fn next(&mut self) -> Option<Self::Item> {
202 self.it.prev()
203 }
204}
205
206impl Cursor for RevStrGraphemes<'_> {
207 #[inline]
208 fn prev(&mut self) -> Option<Self::Item> {
209 self.it.next()
210 }
211
212 #[inline]
213 fn rev_cursor(self) -> impl Cursor<Item = Self::Item> {
214 self.it
215 }
216
217 fn text_offset(&self) -> usize {
218 self.it.text_offset()
219 }
220}
221
222#[derive(Debug)]
225pub(crate) struct RopeGraphemes<'a> {
226 text_offset: usize,
227 text: RopeSlice<'a>,
228 chunks: Chunks<'a>,
229 was_next: Option<bool>,
230 cur_chunk: &'a str,
231 cur_chunk_start: usize,
232 cursor: GraphemeCursor,
233}
234
235impl<'a> RopeGraphemes<'a> {
236 pub(crate) fn new(slice_offset: usize, slice: RopeSlice<'a>) -> RopeGraphemes<'a> {
241 let mut chunks = slice.chunks();
242
243 let (first_chunk, was_next) = match chunks.next() {
246 Some(v) => (v, Some(true)),
247 None => ("", None),
248 };
249
250 RopeGraphemes {
251 text_offset: slice_offset,
252 text: slice,
253 chunks,
254 was_next,
255 cur_chunk: first_chunk,
256 cur_chunk_start: 0,
257 cursor: GraphemeCursor::new(0, slice.len_bytes(), true),
258 }
259 }
260
261 pub(crate) fn new_offset(
269 slice_offset: usize,
270 slice: RopeSlice<'a>,
271 offset: usize,
272 ) -> Result<RopeGraphemes<'a>, TextError> {
273 let Some((mut chunks, chunk_start, _, _)) = slice.get_chunks_at_byte(offset) else {
274 return Err(TextError::ByteIndexOutOfBounds(offset, slice.len_bytes()));
275 };
276
277 let (first_chunk, was_next) = match chunks.next() {
280 Some(v) => (v, Some(true)),
281 None => ("", None),
282 };
283
284 Ok(RopeGraphemes {
285 text_offset: slice_offset,
286 text: slice,
287 chunks,
288 was_next,
289 cur_chunk: first_chunk,
290 cur_chunk_start: chunk_start,
291 cursor: GraphemeCursor::new(offset, slice.len_bytes(), true),
292 })
293 }
294}
295
296impl<'a> Cursor for RopeGraphemes<'a> {
297 fn prev(&mut self) -> Option<Grapheme<'a>> {
298 let a = self.cursor.cur_cursor();
299 let b;
300 loop {
301 match self
302 .cursor
303 .prev_boundary(self.cur_chunk, self.cur_chunk_start)
304 {
305 Ok(None) => {
306 return None;
307 }
308 Ok(Some(n)) => {
309 b = n;
310 break;
311 }
312 Err(GraphemeIncomplete::PrevChunk) => {
313 if self.was_next == Some(true) {
314 self.chunks.prev();
316 }
317 (self.cur_chunk, self.was_next) = match self.chunks.prev() {
318 Some(v) => (v, Some(false)),
319 None => ("", None),
320 };
321 self.cur_chunk_start -= self.cur_chunk.len();
322 }
323 Err(GraphemeIncomplete::PreContext(idx)) => {
324 let (chunk, byte_idx, _, _) = self.text.chunk_at_byte(idx.saturating_sub(1));
325 self.cursor.provide_context(chunk, byte_idx);
326 }
327 _ => unreachable!(),
328 }
329 }
330
331 if a >= self.cur_chunk_start + self.cur_chunk.len() {
332 let a_char = self.text.byte_to_char(a);
333 let b_char = self.text.byte_to_char(b);
334
335 Some(Grapheme {
336 grapheme: Cow::Owned(self.text.slice(b_char..a_char).to_string()),
337 text_bytes: self.text_offset + b..self.text_offset + a,
338 })
339 } else {
340 let a2 = a - self.cur_chunk_start;
341 let b2 = b - self.cur_chunk_start;
342 Some(Grapheme {
343 grapheme: Cow::Borrowed(&self.cur_chunk[b2..a2]),
344 text_bytes: self.text_offset + b..self.text_offset + a,
345 })
346 }
347 }
348
349 #[inline]
350 fn rev_cursor(self) -> impl Cursor<Item = Self::Item> {
351 RevRopeGraphemes { it: self }
352 }
353
354 fn text_offset(&self) -> usize {
355 self.text_offset + self.cursor.cur_cursor()
356 }
357}
358
359impl<'a> Iterator for RopeGraphemes<'a> {
360 type Item = Grapheme<'a>;
361
362 fn next(&mut self) -> Option<Grapheme<'a>> {
363 let a = self.cursor.cur_cursor();
364 let b;
365 loop {
366 match self
367 .cursor
368 .next_boundary(self.cur_chunk, self.cur_chunk_start)
369 {
370 Ok(None) => {
371 return None;
372 }
373 Ok(Some(n)) => {
374 b = n;
375 break;
376 }
377 Err(GraphemeIncomplete::NextChunk) => {
378 self.cur_chunk_start += self.cur_chunk.len();
379 if self.was_next == Some(false) {
380 self.chunks.next();
382 }
383 (self.cur_chunk, self.was_next) = match self.chunks.next() {
384 Some(v) => (v, Some(true)),
385 None => ("", None),
386 };
387 }
388 Err(GraphemeIncomplete::PreContext(idx)) => {
389 let (chunk, byte_idx, _, _) = self.text.chunk_at_byte(idx.saturating_sub(1));
390 self.cursor.provide_context(chunk, byte_idx);
391 }
392 _ => unreachable!(),
393 }
394 }
395
396 if a < self.cur_chunk_start {
397 let a_char = self.text.byte_to_char(a);
398 let b_char = self.text.byte_to_char(b);
399
400 Some(Grapheme {
401 grapheme: Cow::Owned(self.text.slice(a_char..b_char).to_string()),
402 text_bytes: self.text_offset + a..self.text_offset + b,
403 })
404 } else {
405 let a2 = a - self.cur_chunk_start;
406 let b2 = b - self.cur_chunk_start;
407 Some(Grapheme {
408 grapheme: Cow::Borrowed(&self.cur_chunk[a2..b2]),
409 text_bytes: self.text_offset + a..self.text_offset + b,
410 })
411 }
412 }
413}
414
415#[derive(Debug)]
416pub(crate) struct RevRopeGraphemes<'a> {
417 it: RopeGraphemes<'a>,
418}
419
420impl<'a> Iterator for RevRopeGraphemes<'a> {
421 type Item = Grapheme<'a>;
422
423 #[inline]
424 fn next(&mut self) -> Option<Self::Item> {
425 self.it.prev()
426 }
427}
428
429impl Cursor for RevRopeGraphemes<'_> {
430 #[inline]
431 fn prev(&mut self) -> Option<Self::Item> {
432 self.it.next()
433 }
434
435 #[inline]
436 fn rev_cursor(self) -> impl Cursor<Item = Self::Item> {
437 self.it
438 }
439
440 fn text_offset(&self) -> usize {
441 self.it.text_offset()
442 }
443}
444
445#[derive(Debug)]
453pub(crate) struct GlyphIter<Iter> {
454 iter: Iter,
455
456 pos: TextPosition,
457
458 screen_offset: u16,
459 screen_width: u16,
460 screen_pos: (u16, u16),
461
462 tabs: u16,
463 show_ctrl: bool,
464 line_break: bool,
465}
466
467impl<'a, Iter> GlyphIter<Iter>
468where
469 Iter: Iterator<Item = Grapheme<'a>>,
470{
471 pub(crate) fn new(pos: TextPosition, iter: Iter) -> Self {
473 Self {
474 iter,
475 pos,
476 screen_offset: 0,
477 screen_width: u16::MAX,
478 screen_pos: Default::default(),
479 tabs: 8,
480 show_ctrl: false,
481 line_break: true,
482 }
483 }
484
485 pub(crate) fn set_screen_offset(&mut self, offset: u16) {
487 self.screen_offset = offset;
488 }
489
490 pub(crate) fn set_screen_width(&mut self, width: u16) {
492 self.screen_width = width;
493 }
494
495 pub(crate) fn set_tabs(&mut self, tabs: u16) {
497 self.tabs = tabs;
498 }
499
500 pub(crate) fn set_line_break(&mut self, line_break: bool) {
502 self.line_break = line_break;
503 }
504
505 pub(crate) fn set_show_ctrl(&mut self, show_ctrl: bool) {
507 self.show_ctrl = show_ctrl;
508 }
509}
510
511impl<'a, Iter> Iterator for GlyphIter<Iter>
512where
513 Iter: Iterator<Item = Grapheme<'a>>,
514{
515 type Item = Glyph<'a>;
516
517 fn next(&mut self) -> Option<Self::Item> {
518 for grapheme in self.iter.by_ref() {
519 let glyph;
520 let len: u16;
521 let mut lbrk = false;
522
523 match grapheme.grapheme.as_ref() {
526 "\n" | "\r\n" if self.line_break => {
527 lbrk = true;
528 len = if self.show_ctrl { 1 } else { 0 };
529 glyph = Cow::Borrowed(if self.show_ctrl { "\u{2424}" } else { "" });
530 }
531 "\n" | "\r\n" if !self.line_break => {
532 lbrk = false;
533 len = 1;
534 glyph = Cow::Borrowed("\u{2424}");
535 }
536 "\t" => {
537 len = self.tabs - (self.screen_pos.0 % self.tabs);
538 glyph = Cow::Borrowed(if self.show_ctrl { "\u{2409}" } else { " " });
539 }
540 c if ("\x00".."\x20").contains(&c) => {
541 static CCHAR: [&str; 32] = [
542 "\u{2400}", "\u{2401}", "\u{2402}", "\u{2403}", "\u{2404}", "\u{2405}",
543 "\u{2406}", "\u{2407}", "\u{2408}", "\u{2409}", "\u{240A}", "\u{240B}",
544 "\u{240C}", "\u{240D}", "\u{240E}", "\u{240F}", "\u{2410}", "\u{2411}",
545 "\u{2412}", "\u{2413}", "\u{2414}", "\u{2415}", "\u{2416}", "\u{2417}",
546 "\u{2418}", "\u{2419}", "\u{241A}", "\u{241B}", "\u{241C}", "\u{241D}",
547 "\u{241E}", "\u{241F}",
548 ];
549 let c0 = c.bytes().next().expect("byte");
550 len = 1;
551 glyph = Cow::Borrowed(if self.show_ctrl {
552 CCHAR[c0 as usize]
553 } else {
554 "\u{FFFD}"
555 });
556 }
557 c => {
558 len = unicode_display_width::width(c) as u16;
559 glyph = grapheme.grapheme;
560 }
561 }
562
563 let pos = self.pos;
564 let screen_pos = self.screen_pos;
565
566 if lbrk {
567 self.screen_pos.0 = 0;
568 self.screen_pos.1 += 1;
569 self.pos.x = 0;
570 self.pos.y += 1;
571 } else {
572 self.screen_pos.0 += len;
573 self.pos.x += 1;
574 }
575
576 if screen_pos.0 < self.screen_offset {
578 if screen_pos.0 + len > self.screen_offset {
579 return Some(Glyph {
582 glyph: Cow::Borrowed("\u{2203}"),
583 text_bytes: grapheme.text_bytes,
584 screen_width: screen_pos.0 + len - self.screen_offset,
585 pos,
586 screen_pos: (0, screen_pos.1),
587 });
588 } else {
589 }
591 } else if screen_pos.0 + len > self.screen_offset + self.screen_width {
592 if screen_pos.0 < self.screen_offset + self.screen_width {
593 return Some(Glyph {
596 glyph: Cow::Borrowed("\u{2203}"),
597 text_bytes: grapheme.text_bytes,
598 screen_width: screen_pos.0 + len - (self.screen_offset + self.screen_width),
599 pos,
600 screen_pos: (screen_pos.0 - self.screen_offset, screen_pos.1),
601 });
602 } else {
603 if !self.line_break {
605 break;
606 }
607 }
608 } else {
609 return Some(Glyph {
610 glyph,
611 text_bytes: grapheme.text_bytes,
612 screen_width: len,
613 pos,
614 screen_pos: (screen_pos.0 - self.screen_offset, screen_pos.1),
615 });
616 }
617 }
618
619 None
620 }
621}
622
623#[cfg(test)]
624mod test_str {
625 use crate::grapheme::StrGraphemes;
626 use crate::Cursor;
627
628 #[test]
629 fn test_str_graphemes1() {
630 let s = String::from("qwertz");
632
633 let mut s0 = StrGraphemes::new(0, &s);
634 assert_eq!(s0.next().unwrap(), "q");
635 assert_eq!(s0.next().unwrap(), "w");
636 assert_eq!(s0.next().unwrap(), "e");
637 assert_eq!(s0.next().unwrap(), "r");
638 assert_eq!(s0.next().unwrap(), "t");
639 assert_eq!(s0.next().unwrap(), "z");
640 assert!(s0.next().is_none());
641 assert_eq!(s0.prev().unwrap(), "z");
642 assert_eq!(s0.prev().unwrap(), "t");
643 assert_eq!(s0.prev().unwrap(), "r");
644 assert_eq!(s0.prev().unwrap(), "e");
645 assert_eq!(s0.prev().unwrap(), "w");
646 assert_eq!(s0.prev().unwrap(), "q");
647
648 let mut s0 = StrGraphemes::new(1, &s[1..s.len() - 1]);
649 assert_eq!(s0.next().unwrap(), "w");
650 assert_eq!(s0.next().unwrap(), "e");
651 assert_eq!(s0.next().unwrap(), "r");
652 assert_eq!(s0.next().unwrap(), "t");
653 assert!(s0.next().is_none());
654 assert_eq!(s0.prev().unwrap(), "t");
655 assert_eq!(s0.prev().unwrap(), "r");
656 assert_eq!(s0.prev().unwrap(), "e");
657 assert_eq!(s0.prev().unwrap(), "w");
658
659 let mut s0 = StrGraphemes::new(3, &s[3..3]);
660 assert!(s0.next().is_none());
661 assert!(s0.prev().is_none());
662 }
663
664 #[test]
665 fn test_str_graphemes2() {
666 let s = String::from("w🤷♂️xw🤷♀️xw🤦♂️xw❤️xw🤦♀️xw💕🙍🏿♀️x");
668
669 let mut s0 = StrGraphemes::new(0, &s);
670 assert_eq!(s0.next().unwrap(), "w");
671 assert_eq!(s0.next().unwrap(), "🤷♂️");
672 assert_eq!(s0.next().unwrap(), "x");
673 assert_eq!(s0.next().unwrap(), "w");
674 assert_eq!(s0.next().unwrap(), "🤷♀️");
675 assert_eq!(s0.next().unwrap(), "x");
676 assert_eq!(s0.next().unwrap(), "w");
677 assert_eq!(s0.next().unwrap(), "🤦♂️");
678 assert_eq!(s0.next().unwrap(), "x");
679 assert_eq!(s0.next().unwrap(), "w");
680 assert_eq!(s0.next().unwrap(), "❤️");
681 assert_eq!(s0.next().unwrap(), "x");
682 assert_eq!(s0.next().unwrap(), "w");
683 assert_eq!(s0.next().unwrap(), "🤦♀️");
684 assert_eq!(s0.next().unwrap(), "x");
685 assert_eq!(s0.next().unwrap(), "w");
686 assert_eq!(s0.next().unwrap(), "💕");
687 assert_eq!(s0.next().unwrap(), "🙍🏿♀️");
688 assert_eq!(s0.next().unwrap(), "x");
689 assert!(s0.next().is_none());
690 assert_eq!(s0.prev().unwrap(), "x");
691 assert_eq!(s0.prev().unwrap(), "🙍🏿♀️");
692 assert_eq!(s0.prev().unwrap(), "💕");
693 assert_eq!(s0.prev().unwrap(), "w");
694 assert_eq!(s0.prev().unwrap(), "x");
695 assert_eq!(s0.prev().unwrap(), "🤦♀️");
696 assert_eq!(s0.prev().unwrap(), "w");
697 assert_eq!(s0.prev().unwrap(), "x");
698 assert_eq!(s0.prev().unwrap(), "❤️");
699 assert_eq!(s0.prev().unwrap(), "w");
700 assert_eq!(s0.prev().unwrap(), "x");
701 assert_eq!(s0.prev().unwrap(), "🤦♂️");
702 assert_eq!(s0.prev().unwrap(), "w");
703 assert_eq!(s0.prev().unwrap(), "x");
704 assert_eq!(s0.prev().unwrap(), "🤷♀️");
705 assert_eq!(s0.prev().unwrap(), "w");
706 assert_eq!(s0.prev().unwrap(), "x");
707 assert_eq!(s0.prev().unwrap(), "🤷♂️");
708 assert_eq!(s0.prev().unwrap(), "w");
709 }
710
711 #[test]
712 fn test_str_graphemes3() {
713 let s = String::from("qwertz");
715 let mut s0 = StrGraphemes::new_offset(0, &s, 3);
716 assert_eq!(s0.next().unwrap(), "r");
717 assert_eq!(s0.prev().unwrap(), "r");
718 assert_eq!(s0.prev().unwrap(), "e");
719
720 let mut s0 = StrGraphemes::new_offset(0, &s, 3);
721 assert_eq!(s0.next().unwrap().text_bytes(), 3..4);
722 assert_eq!(s0.prev().unwrap().text_bytes(), 3..4);
723 assert_eq!(s0.prev().unwrap().text_bytes(), 2..3);
724
725 let s = String::from("w🤷♂️🤷♀️🤦♂️❤️🤦♀️💕🙍🏿♀️x");
726 let mut s0 = StrGraphemes::new_offset(0, &s, 21);
727 assert_eq!(s0.next().unwrap(), "♀\u{fe0f}");
728 assert_eq!(s0.next().unwrap(), "🤦\u{200d}♂\u{fe0f}");
729 assert_eq!(s0.prev().unwrap(), "🤦\u{200d}♂\u{fe0f}");
730 assert_eq!(s0.prev().unwrap(), "🤷\u{200d}♀\u{fe0f}");
731
732 let s = String::from("w🤷♂️🤷♀️🤦♂️❤️🤦♀️💕🙍🏿♀️x");
733 let mut s0 = StrGraphemes::new_offset(0, &s, 21);
734 assert_eq!(s0.next().unwrap().text_bytes(), 21..27);
735 assert_eq!(s0.next().unwrap().text_bytes(), 27..40);
736 assert_eq!(s0.prev().unwrap().text_bytes(), 27..40);
737 assert_eq!(s0.prev().unwrap().text_bytes(), 14..27);
738 }
739
740 #[test]
741 fn test_str_graphemes4() {
742 let s = String::from("qwertz");
744 let mut s0 = StrGraphemes::new_offset(1, &s[1..5], 2);
745 s0.next();
746 assert_eq!(s0.text_offset(), 4);
747 s0.next();
748 assert_eq!(s0.text_offset(), 5);
749 s0.next();
750 assert_eq!(s0.text_offset(), 5);
751 s0.next();
752 assert_eq!(s0.text_offset(), 5);
753 s0.prev();
754 assert_eq!(s0.text_offset(), 4);
755 s0.prev();
756 assert_eq!(s0.text_offset(), 3);
757 s0.prev();
758 assert_eq!(s0.text_offset(), 2);
759 s0.prev();
760 assert_eq!(s0.text_offset(), 1);
761 s0.prev();
762 assert_eq!(s0.text_offset(), 1);
763 }
764
765 #[test]
766 fn test_str_graphemes5() {
767 let s = String::from("qwertz");
769 let mut s0 = StrGraphemes::new_offset(1, &s[1..5], 2).rev_cursor();
770 assert_eq!(s0.next().unwrap(), "e");
771 assert_eq!(s0.text_offset(), 2);
772
773 assert_eq!(s0.next().unwrap(), "w");
774 assert_eq!(s0.text_offset(), 1);
775
776 assert_eq!(s0.prev().unwrap(), "w");
777 assert_eq!(s0.text_offset(), 2);
778
779 assert_eq!(s0.prev().unwrap(), "e");
780 assert_eq!(s0.text_offset(), 3);
781
782 assert_eq!(s0.prev().unwrap(), "r");
783 assert_eq!(s0.text_offset(), 4);
784
785 assert_eq!(s0.prev().unwrap(), "t");
786 assert_eq!(s0.text_offset(), 5);
787 }
788}
789
790#[cfg(test)]
791mod test_rope {
792 use crate::grapheme::RopeGraphemes;
793 use crate::Cursor;
794 use ropey::Rope;
795
796 #[test]
797 fn test_rope_graphemes1() {
798 let s = Rope::from("qwertz");
800
801 let mut s0 = RopeGraphemes::new(0, s.byte_slice(..));
802 assert_eq!(s0.next().unwrap(), "q");
803 assert_eq!(s0.next().unwrap(), "w");
804 assert_eq!(s0.next().unwrap(), "e");
805 assert_eq!(s0.next().unwrap(), "r");
806 assert_eq!(s0.next().unwrap(), "t");
807 assert_eq!(s0.next().unwrap(), "z");
808 assert!(s0.next().is_none());
809 assert_eq!(s0.prev().unwrap(), "z");
810 assert_eq!(s0.prev().unwrap(), "t");
811 assert_eq!(s0.prev().unwrap(), "r");
812 assert_eq!(s0.prev().unwrap(), "e");
813 assert_eq!(s0.prev().unwrap(), "w");
814 assert_eq!(s0.prev().unwrap(), "q");
815
816 let mut s0 = RopeGraphemes::new(1, s.byte_slice(1..s.len_bytes() - 1));
817 assert_eq!(s0.next().unwrap(), "w");
818 assert_eq!(s0.next().unwrap(), "e");
819 assert_eq!(s0.next().unwrap(), "r");
820 assert_eq!(s0.next().unwrap(), "t");
821 assert!(s0.next().is_none());
822 assert_eq!(s0.prev().unwrap(), "t");
823 assert_eq!(s0.prev().unwrap(), "r");
824 assert_eq!(s0.prev().unwrap(), "e");
825 assert_eq!(s0.prev().unwrap(), "w");
826
827 let mut s0 = RopeGraphemes::new(3, s.byte_slice(3..3));
828 assert!(s0.next().is_none());
829 assert!(s0.prev().is_none());
830 }
831
832 #[test]
833 fn test_rope_graphemes2() {
834 let s = Rope::from("w🤷♂️xw🤷♀️xw🤦♂️xw❤️xw🤦♀️xw💕🙍🏿♀️x");
836
837 let mut s0 = RopeGraphemes::new(0, s.byte_slice(..));
838 assert_eq!(s0.next().unwrap(), "w");
839 assert_eq!(s0.next().unwrap(), "🤷♂️");
840 assert_eq!(s0.next().unwrap(), "x");
841 assert_eq!(s0.next().unwrap(), "w");
842 assert_eq!(s0.next().unwrap(), "🤷♀️");
843 assert_eq!(s0.next().unwrap(), "x");
844 assert_eq!(s0.next().unwrap(), "w");
845 assert_eq!(s0.next().unwrap(), "🤦♂️");
846 assert_eq!(s0.next().unwrap(), "x");
847 assert_eq!(s0.next().unwrap(), "w");
848 assert_eq!(s0.next().unwrap(), "❤️");
849 assert_eq!(s0.next().unwrap(), "x");
850 assert_eq!(s0.next().unwrap(), "w");
851 assert_eq!(s0.next().unwrap(), "🤦♀️");
852 assert_eq!(s0.next().unwrap(), "x");
853 assert_eq!(s0.next().unwrap(), "w");
854 assert_eq!(s0.next().unwrap(), "💕");
855 assert_eq!(s0.next().unwrap(), "🙍🏿♀️");
856 assert_eq!(s0.next().unwrap(), "x");
857 assert!(s0.next().is_none());
858 assert_eq!(s0.prev().unwrap(), "x");
859 assert_eq!(s0.prev().unwrap(), "🙍🏿♀️");
860 assert_eq!(s0.prev().unwrap(), "💕");
861 assert_eq!(s0.prev().unwrap(), "w");
862 assert_eq!(s0.prev().unwrap(), "x");
863 assert_eq!(s0.prev().unwrap(), "🤦♀️");
864 assert_eq!(s0.prev().unwrap(), "w");
865 assert_eq!(s0.prev().unwrap(), "x");
866 assert_eq!(s0.prev().unwrap(), "❤️");
867 assert_eq!(s0.prev().unwrap(), "w");
868 assert_eq!(s0.prev().unwrap(), "x");
869 assert_eq!(s0.prev().unwrap(), "🤦♂️");
870 assert_eq!(s0.prev().unwrap(), "w");
871 assert_eq!(s0.prev().unwrap(), "x");
872 assert_eq!(s0.prev().unwrap(), "🤷♀️");
873 assert_eq!(s0.prev().unwrap(), "w");
874 assert_eq!(s0.prev().unwrap(), "x");
875 assert_eq!(s0.prev().unwrap(), "🤷♂️");
876 assert_eq!(s0.prev().unwrap(), "w");
877 }
878
879 #[test]
880 fn test_rope_graphemes3() {
881 let s = Rope::from("qwertz");
883 let mut s0 = RopeGraphemes::new_offset(0, s.byte_slice(..), 3).expect("fine");
884 assert_eq!(s0.next().unwrap(), "r");
885 assert_eq!(s0.prev().unwrap(), "r");
886 assert_eq!(s0.prev().unwrap(), "e");
887
888 let mut s0 = RopeGraphemes::new_offset(0, s.byte_slice(..), 3).expect("fine");
889 assert_eq!(s0.next().unwrap().text_bytes(), 3..4);
890 assert_eq!(s0.prev().unwrap().text_bytes(), 3..4);
891 assert_eq!(s0.prev().unwrap().text_bytes(), 2..3);
892
893 let s = Rope::from("w🤷♂️🤷♀️🤦♂️❤️🤦♀️💕🙍🏿♀️x");
894 let mut s0 = RopeGraphemes::new_offset(0, s.byte_slice(..), 21).expect("fine");
895 assert_eq!(s0.next().unwrap(), "♀\u{fe0f}");
896 assert_eq!(s0.next().unwrap(), "🤦\u{200d}♂\u{fe0f}");
897 assert_eq!(s0.prev().unwrap(), "🤦\u{200d}♂\u{fe0f}");
898 assert_eq!(s0.prev().unwrap(), "🤷\u{200d}♀\u{fe0f}");
899
900 let s = Rope::from("w🤷♂️🤷♀️🤦♂️❤️🤦♀️💕🙍🏿♀️x");
901 let mut s0 = RopeGraphemes::new_offset(0, s.byte_slice(..), 21).expect("fine");
902 assert_eq!(s0.next().unwrap().text_bytes(), 21..27);
903 assert_eq!(s0.next().unwrap().text_bytes(), 27..40);
904 assert_eq!(s0.prev().unwrap().text_bytes(), 27..40);
905 assert_eq!(s0.prev().unwrap().text_bytes(), 14..27);
906 }
907
908 #[test]
909 fn test_rope_graphemes4() {
910 let s = Rope::from("qwertz");
912 let mut s0 = RopeGraphemes::new_offset(1, s.byte_slice(1..5), 2).expect("fine");
913 s0.next();
914 assert_eq!(s0.text_offset(), 4);
915 s0.next();
916 assert_eq!(s0.text_offset(), 5);
917 s0.next();
918 assert_eq!(s0.text_offset(), 5);
919 s0.next();
920 assert_eq!(s0.text_offset(), 5);
921 s0.prev();
922 assert_eq!(s0.text_offset(), 4);
923 s0.prev();
924 assert_eq!(s0.text_offset(), 3);
925 s0.prev();
926 assert_eq!(s0.text_offset(), 2);
927 s0.prev();
928 assert_eq!(s0.text_offset(), 1);
929 s0.prev();
930 assert_eq!(s0.text_offset(), 1);
931 }
932
933 #[test]
934 fn test_rope_graphemes5() {
935 let s = Rope::from("qwertz");
937 let mut s0 = RopeGraphemes::new_offset(1, s.byte_slice(1..5), 2)
938 .expect("fine")
939 .rev_cursor();
940 assert_eq!(s0.next().unwrap(), "e");
941 assert_eq!(s0.text_offset(), 2);
942
943 assert_eq!(s0.next().unwrap(), "w");
944 assert_eq!(s0.text_offset(), 1);
945
946 assert_eq!(s0.prev().unwrap(), "w");
947 assert_eq!(s0.text_offset(), 2);
948
949 assert_eq!(s0.prev().unwrap(), "e");
950 assert_eq!(s0.text_offset(), 3);
951
952 assert_eq!(s0.prev().unwrap(), "r");
953 assert_eq!(s0.text_offset(), 4);
954
955 assert_eq!(s0.prev().unwrap(), "t");
956 assert_eq!(s0.text_offset(), 5);
957 }
958
959 #[test]
960 fn test_rope_graphemes6() {
961 let s = Rope::from(
963 "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
964 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
965 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
966 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
967 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
968 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
969 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
970 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
971 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
972 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
973 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
974 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
975 "
976 );
977 assert_eq!(s.len_bytes(), 1200);
978 let mut s0 = RopeGraphemes::new_offset(1, s.byte_slice(1..1199), 0).expect("fine");
979 assert_eq!(s0.nth(598).unwrap(), "J");
980
981 assert_eq!(s0.next().unwrap(), "0");
982 assert_eq!(s0.text_offset(), 601);
983 assert_eq!(s0.next().unwrap(), "1");
984 assert_eq!(s0.text_offset(), 602);
985 assert_eq!(s0.prev().unwrap(), "1");
986 assert_eq!(s0.text_offset(), 601);
987 assert_eq!(s0.prev().unwrap(), "0");
988 assert_eq!(s0.text_offset(), 600);
989 assert_eq!(s0.prev().unwrap(), "J");
990 assert_eq!(s0.text_offset(), 599);
991 }
992
993 #[test]
994 fn test_rope_graphemes7() {
995 let s = Rope::from(
997 "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
998 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
999 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
1000 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
1001 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
1002 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghi🤷♂️\
1003 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
1004 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
1005 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
1006 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
1007 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678)\
1008 abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghiJ\
1009 "
1010 );
1011 assert_eq!(s.len_bytes(), 1212);
1012 assert_eq!(s.chunks().next().unwrap().len(), 606);
1013 let mut s0 = RopeGraphemes::new_offset(1, s.byte_slice(1..1199), 0).expect("fine");
1014 assert_eq!(s0.nth(598).unwrap(), "🤷♂️");
1015
1016 assert_eq!(s0.next().unwrap(), "0");
1017 assert_eq!(s0.text_offset(), 613);
1018 assert_eq!(s0.next().unwrap(), "1");
1019 assert_eq!(s0.text_offset(), 614);
1020 assert_eq!(s0.prev().unwrap(), "1");
1021 assert_eq!(s0.text_offset(), 613);
1022 assert_eq!(s0.prev().unwrap(), "0");
1023 assert_eq!(s0.text_offset(), 612);
1024 assert_eq!(s0.prev().unwrap(), "🤷♂️");
1025 assert_eq!(s0.text_offset(), 599);
1026 assert_eq!(s0.prev().unwrap(), "i");
1027 assert_eq!(s0.text_offset(), 598);
1028
1029 assert_eq!(s0.next().unwrap(), "i");
1030 assert_eq!(s0.text_offset(), 599);
1031 assert_eq!(s0.next().unwrap(), "🤷♂️");
1032 assert_eq!(s0.text_offset(), 612);
1033 assert_eq!(s0.next().unwrap(), "0");
1034 assert_eq!(s0.text_offset(), 613);
1035 assert_eq!(s0.next().unwrap(), "1");
1036 assert_eq!(s0.text_offset(), 614);
1037 }
1038}
1039
1040#[cfg(test)]
1041mod test_glyph {
1042 use crate::grapheme::{GlyphIter, RopeGraphemes};
1043 use crate::TextPosition;
1044 use ropey::Rope;
1045
1046 #[test]
1047 fn test_glyph1() {
1048 let s = Rope::from(
1049 r#"0123456789
1050abcdefghij
1051jklöjklöjk
1052uiopü+uiop"#,
1053 );
1054 let r = RopeGraphemes::new(0, s.byte_slice(..));
1055 let mut glyphs = GlyphIter::new(TextPosition::new(0, 0), r);
1056
1057 let n = glyphs.next().unwrap();
1058 assert_eq!(n.glyph(), "0");
1059 assert_eq!(n.text_bytes(), 0..1);
1060 assert_eq!(n.screen_pos(), (0, 0));
1061 assert_eq!(n.pos(), TextPosition::new(0, 0));
1062 assert_eq!(n.screen_width(), 1);
1063
1064 let n = glyphs.next().unwrap();
1065 assert_eq!(n.glyph(), "1");
1066 assert_eq!(n.text_bytes(), 1..2);
1067 assert_eq!(n.screen_pos(), (1, 0));
1068 assert_eq!(n.pos(), TextPosition::new(1, 0));
1069 assert_eq!(n.screen_width(), 1);
1070
1071 let n = glyphs.next().unwrap();
1072 assert_eq!(n.glyph(), "2");
1073 assert_eq!(n.text_bytes(), 2..3);
1074 assert_eq!(n.screen_pos(), (2, 0));
1075 assert_eq!(n.pos(), TextPosition::new(2, 0));
1076 assert_eq!(n.screen_width(), 1);
1077
1078 let n = glyphs.nth(7).unwrap();
1079 assert_eq!(n.glyph(), "");
1080 assert_eq!(n.text_bytes(), 10..11);
1081 assert_eq!(n.screen_pos(), (10, 0));
1082 assert_eq!(n.pos(), TextPosition::new(10, 0));
1083 assert_eq!(n.screen_width(), 0);
1084
1085 let n = glyphs.next().unwrap();
1086 assert_eq!(n.glyph(), "a");
1087 assert_eq!(n.text_bytes(), 11..12);
1088 assert_eq!(n.screen_pos(), (0, 1));
1089 assert_eq!(n.pos(), TextPosition::new(0, 1));
1090 assert_eq!(n.screen_width(), 1);
1091 }
1092
1093 #[test]
1094 fn test_glyph2() {
1095 let s = Rope::from(
1097 r#"0123456789
1098abcdefghij
1099jklöjklöjk
1100uiopü+uiop"#,
1101 );
1102 let r = RopeGraphemes::new(0, s.byte_slice(..));
1103 let mut glyphs = GlyphIter::new(TextPosition::new(0, 0), r);
1104 glyphs.set_screen_offset(2);
1105 glyphs.set_screen_width(100);
1106
1107 let n = glyphs.next().unwrap();
1108 assert_eq!(n.glyph(), "2");
1109 assert_eq!(n.text_bytes(), 2..3);
1110 assert_eq!(n.screen_pos(), (0, 0));
1111 assert_eq!(n.pos(), TextPosition::new(2, 0));
1112 assert_eq!(n.screen_width(), 1);
1113
1114 let n = glyphs.next().unwrap();
1115 assert_eq!(n.glyph(), "3");
1116 assert_eq!(n.text_bytes(), 3..4);
1117 assert_eq!(n.screen_pos(), (1, 0));
1118 assert_eq!(n.pos(), TextPosition::new(3, 0));
1119 assert_eq!(n.screen_width(), 1);
1120
1121 let n = glyphs.nth(6).unwrap();
1122 assert_eq!(n.glyph(), "");
1123 assert_eq!(n.text_bytes(), 10..11);
1124 assert_eq!(n.screen_pos(), (8, 0));
1125 assert_eq!(n.pos(), TextPosition::new(10, 0));
1126 assert_eq!(n.screen_width(), 0);
1127
1128 let n = glyphs.next().unwrap();
1129 assert_eq!(n.glyph(), "c");
1130 assert_eq!(n.text_bytes(), 13..14);
1131 assert_eq!(n.screen_pos(), (0, 1));
1132 assert_eq!(n.pos(), TextPosition::new(2, 1));
1133 assert_eq!(n.screen_width(), 1);
1134 }
1135
1136 #[test]
1137 fn test_glyph3() {
1138 let s = Rope::from(
1140 r#"0123456789
1141abcdefghij
1142jklöjklöjk
1143uiopü+uiop"#,
1144 );
1145 let r = RopeGraphemes::new(0, s.byte_slice(..));
1146 let mut glyphs = GlyphIter::new(TextPosition::new(0, 0), r);
1147 glyphs.set_screen_offset(2);
1148 glyphs.set_screen_width(6);
1149
1150 let n = glyphs.next().unwrap();
1151 assert_eq!(n.glyph(), "2");
1152 assert_eq!(n.text_bytes(), 2..3);
1153 assert_eq!(n.screen_pos(), (0, 0));
1154 assert_eq!(n.pos(), TextPosition::new(2, 0));
1155 assert_eq!(n.screen_width(), 1);
1156
1157 let n = glyphs.next().unwrap();
1158 assert_eq!(n.glyph(), "3");
1159 assert_eq!(n.text_bytes(), 3..4);
1160 assert_eq!(n.screen_pos(), (1, 0));
1161 assert_eq!(n.pos(), TextPosition::new(3, 0));
1162 assert_eq!(n.screen_width(), 1);
1163
1164 let n = glyphs.nth(2).unwrap();
1165 assert_eq!(n.glyph(), "6");
1166
1167 let n = glyphs.next().unwrap();
1168 assert_eq!(n.glyph(), "7");
1169 assert_eq!(n.text_bytes(), 7..8);
1170 assert_eq!(n.screen_pos(), (5, 0));
1171 assert_eq!(n.pos(), TextPosition::new(7, 0));
1172 assert_eq!(n.screen_width(), 1);
1173
1174 let n = glyphs.next().unwrap();
1175 assert_eq!(n.glyph(), "c");
1176 assert_eq!(n.text_bytes(), 13..14);
1177 assert_eq!(n.screen_pos(), (0, 1));
1178 assert_eq!(n.pos(), TextPosition::new(2, 1));
1179 assert_eq!(n.screen_width(), 1);
1180 }
1181
1182 #[test]
1183 fn test_glyph4() {
1184 let s = Rope::from(
1186 "012\t3456789
1187abcdefghij
1188jklöjklöjk
1189uiopü+uiop",
1190 );
1191 let r = RopeGraphemes::new(0, s.byte_slice(..));
1192 let mut glyphs = GlyphIter::new(TextPosition::new(0, 0), r);
1193 glyphs.set_screen_offset(2);
1194 glyphs.set_screen_width(100);
1195
1196 let n = glyphs.next().unwrap();
1197 assert_eq!(n.glyph(), "2");
1198 assert_eq!(n.text_bytes(), 2..3);
1199 assert_eq!(n.screen_pos(), (0, 0));
1200 assert_eq!(n.pos(), TextPosition::new(2, 0));
1201 assert_eq!(n.screen_width(), 1);
1202
1203 let n = glyphs.next().unwrap();
1204 assert_eq!(n.glyph(), " ");
1205 assert_eq!(n.text_bytes(), 3..4);
1206 assert_eq!(n.screen_pos(), (1, 0));
1207 assert_eq!(n.pos(), TextPosition::new(3, 0));
1208 assert_eq!(n.screen_width(), 5);
1209
1210 let n = glyphs.nth(7).unwrap();
1211 assert_eq!(n.glyph(), "");
1212 assert_eq!(n.text_bytes(), 11..12);
1213 assert_eq!(n.screen_pos(), (13, 0));
1214 assert_eq!(n.pos(), TextPosition::new(11, 0));
1215 assert_eq!(n.screen_width(), 0);
1216
1217 let n = glyphs.next().unwrap();
1218 assert_eq!(n.glyph(), "c");
1219 assert_eq!(n.text_bytes(), 14..15);
1220 assert_eq!(n.screen_pos(), (0, 1));
1221 assert_eq!(n.pos(), TextPosition::new(2, 1));
1222 assert_eq!(n.screen_width(), 1);
1223 }
1224
1225 #[test]
1226 fn test_glyph5() {
1227 let s = Rope::from(
1229 "0\t12345678\t9
1230abcdefghij
1231jklöjklöjk
1232uiopü+uiop",
1233 );
1234 let r = RopeGraphemes::new(0, s.byte_slice(..));
1235 let mut glyphs = GlyphIter::new(TextPosition::new(0, 0), r);
1236 glyphs.set_screen_offset(2);
1237 glyphs.set_screen_width(20);
1238
1239 let n = glyphs.next().unwrap();
1240 assert_eq!(n.glyph(), "∃");
1241 assert_eq!(n.text_bytes(), 1..2);
1242 assert_eq!(n.screen_pos(), (0, 0));
1243 assert_eq!(n.pos(), TextPosition::new(1, 0));
1244 assert_eq!(n.screen_width(), 6);
1245
1246 let n = glyphs.next().unwrap();
1247 assert_eq!(n.glyph(), "1");
1248 assert_eq!(n.text_bytes(), 2..3);
1249 assert_eq!(n.screen_pos(), (6, 0));
1250 assert_eq!(n.pos(), TextPosition::new(2, 0));
1251 assert_eq!(n.screen_width(), 1);
1252
1253 let n = glyphs.nth(6).unwrap();
1254 assert_eq!(n.glyph(), "8");
1255
1256 let n = glyphs.next().unwrap();
1257 assert_eq!(n.glyph(), "∃");
1258 assert_eq!(n.text_bytes(), 10..11);
1259 assert_eq!(n.screen_pos(), (14, 0));
1260 assert_eq!(n.pos(), TextPosition::new(10, 0));
1261 assert_eq!(n.screen_width(), 2);
1262
1263 let n = glyphs.next().unwrap();
1264 assert_eq!(n.glyph(), "c");
1265 assert_eq!(n.text_bytes(), 15..16);
1266 assert_eq!(n.screen_pos(), (0, 1));
1267 assert_eq!(n.pos(), TextPosition::new(2, 1));
1268 assert_eq!(n.screen_width(), 1);
1269 }
1270}