1use crate::keymap::{At, CharSearch, Movement, RepeatCount, Word};
3use std::cmp::min;
4use std::fmt;
5use std::iter;
6use std::ops::{Deref, Index, Range};
7use std::string::Drain;
8use unicode_segmentation::UnicodeSegmentation;
9
10pub(crate) const MAX_LINE: usize = 4096;
12pub(crate) const INDENT: &str = " ";
13
14#[derive(Clone, Copy)]
16pub enum WordAction {
17 Capitalize,
19 Lowercase,
21 Uppercase,
23}
24
25#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
27pub enum Direction {
28 #[default]
30 Forward,
31 Backward,
33}
34
35pub trait DeleteListener {
37 fn start_killing(&mut self) {}
40 fn delete(&mut self, idx: usize, string: &str, dir: Direction);
42 fn stop_killing(&mut self) {}
45}
46
47pub trait ChangeListener: DeleteListener {
49 fn insert_char(&mut self, idx: usize, c: char);
51 fn insert_str(&mut self, idx: usize, string: &str);
53 fn replace(&mut self, idx: usize, old: &str, new: &str);
55}
56
57pub(crate) struct NoListener;
58
59impl DeleteListener for NoListener {
60 fn delete(&mut self, _idx: usize, _string: &str, _dir: Direction) {}
61}
62impl ChangeListener for NoListener {
63 fn insert_char(&mut self, _idx: usize, _c: char) {}
64
65 fn insert_str(&mut self, _idx: usize, _string: &str) {}
66
67 fn replace(&mut self, _idx: usize, _old: &str, _new: &str) {}
68}
69
70pub struct LineBuffer {
76 buf: String, pos: usize, can_growth: bool, }
80
81impl fmt::Debug for LineBuffer {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 f.debug_struct("LineBuffer")
84 .field("buf", &self.buf)
85 .field("pos", &self.pos)
86 .finish()
87 }
88}
89
90impl LineBuffer {
91 #[must_use]
93 pub fn with_capacity(capacity: usize) -> Self {
94 Self {
95 buf: String::with_capacity(capacity),
96 pos: 0,
97 can_growth: false,
98 }
99 }
100
101 pub(crate) fn can_growth(mut self, can_growth: bool) -> Self {
103 self.can_growth = can_growth;
104 self
105 }
106
107 fn must_truncate(&self, new_len: usize) -> bool {
108 !self.can_growth && new_len > self.buf.capacity()
109 }
110
111 #[cfg(test)]
112 pub(crate) fn init(line: &str, pos: usize) -> Self {
113 let mut lb = Self::with_capacity(MAX_LINE);
114 assert!(lb.insert_str(0, line, &mut NoListener));
115 lb.set_pos(pos);
116 lb
117 }
118
119 #[must_use]
121 pub fn as_str(&self) -> &str {
122 &self.buf
123 }
124
125 #[must_use]
127 pub fn into_string(self) -> String {
128 self.buf
129 }
130
131 #[must_use]
133 pub fn pos(&self) -> usize {
134 self.pos
135 }
136
137 pub fn set_pos(&mut self, pos: usize) {
139 assert!(pos <= self.buf.len());
140 self.pos = pos;
141 }
142
143 #[must_use]
145 pub fn len(&self) -> usize {
146 self.buf.len()
147 }
148
149 #[must_use]
151 pub fn is_empty(&self) -> bool {
152 self.buf.is_empty()
153 }
154
155 pub fn update<C: ChangeListener>(&mut self, buf: &str, pos: usize, cl: &mut C) {
157 assert!(pos <= buf.len());
158 let end = self.len();
159 self.drain(0..end, Direction::default(), cl);
160 let max = self.buf.capacity();
161 if self.must_truncate(buf.len()) {
162 self.insert_str(0, &buf[..max], cl);
163 if pos > max {
164 self.pos = max;
165 } else {
166 self.pos = pos;
167 }
168 } else {
169 self.insert_str(0, buf, cl);
170 self.pos = pos;
171 }
172 }
173
174 fn end_of_line(&self) -> usize {
175 if let Some(n) = self.buf[self.pos..].find('\n') {
176 n + self.pos
177 } else {
178 self.buf.len()
179 }
180 }
181
182 fn start_of_line(&self) -> usize {
183 if let Some(i) = self.buf[..self.pos].rfind('\n') {
184 i + 1
186 } else {
187 0
188 }
189 }
190
191 pub(crate) fn grapheme_at_cursor(&self) -> Option<&str> {
193 if self.pos == self.buf.len() {
194 None
195 } else {
196 self.buf[self.pos..].graphemes(true).next()
197 }
198 }
199
200 #[must_use]
203 pub fn next_pos(&self, n: RepeatCount) -> Option<usize> {
204 if self.pos == self.buf.len() {
205 return None;
206 }
207 self.buf[self.pos..]
208 .grapheme_indices(true)
209 .take(n)
210 .last()
211 .map(|(i, s)| i + self.pos + s.len())
212 }
213
214 fn prev_pos(&self, n: RepeatCount) -> Option<usize> {
217 if self.pos == 0 {
218 return None;
219 }
220 self.buf[..self.pos]
221 .grapheme_indices(true)
222 .rev()
223 .take(n)
224 .last()
225 .map(|(i, _)| i)
226 }
227
228 pub fn insert<C: ChangeListener>(
233 &mut self,
234 ch: char,
235 n: RepeatCount,
236 cl: &mut C,
237 ) -> Option<bool> {
238 let shift = ch.len_utf8() * n;
239 if self.must_truncate(self.buf.len() + shift) {
240 return None;
241 }
242 let push = self.pos == self.buf.len();
243 if n == 1 {
244 self.buf.insert(self.pos, ch);
245 cl.insert_char(self.pos, ch);
246 } else {
247 let text = iter::repeat(ch).take(n).collect::<String>();
248 let pos = self.pos;
249 self.insert_str(pos, &text, cl);
250 }
251 self.pos += shift;
252 Some(push)
253 }
254
255 pub fn yank<C: ChangeListener>(
259 &mut self,
260 text: &str,
261 n: RepeatCount,
262 cl: &mut C,
263 ) -> Option<bool> {
264 let shift = text.len() * n;
265 if text.is_empty() || self.must_truncate(self.buf.len() + shift) {
266 return None;
267 }
268 let push = self.pos == self.buf.len();
269 let pos = self.pos;
270 if n == 1 {
271 self.insert_str(pos, text, cl);
272 } else {
273 let text = text.repeat(n);
274 self.insert_str(pos, &text, cl);
275 }
276 self.pos += shift;
277 Some(push)
278 }
279
280 pub fn yank_pop<C: ChangeListener>(
282 &mut self,
283 yank_size: usize,
284 text: &str,
285 cl: &mut C,
286 ) -> Option<bool> {
287 let end = self.pos;
288 let start = end - yank_size;
289 self.drain(start..end, Direction::default(), cl);
290 self.pos -= yank_size;
291 self.yank(text, 1, cl)
292 }
293
294 pub fn move_backward(&mut self, n: RepeatCount) -> bool {
296 match self.prev_pos(n) {
297 Some(pos) => {
298 self.pos = pos;
299 true
300 }
301 None => false,
302 }
303 }
304
305 pub fn move_forward(&mut self, n: RepeatCount) -> bool {
307 match self.next_pos(n) {
308 Some(pos) => {
309 self.pos = pos;
310 true
311 }
312 None => false,
313 }
314 }
315
316 pub fn move_buffer_start(&mut self) -> bool {
318 if self.pos > 0 {
319 self.pos = 0;
320 true
321 } else {
322 false
323 }
324 }
325
326 pub fn move_buffer_end(&mut self) -> bool {
328 if self.pos == self.buf.len() {
329 false
330 } else {
331 self.pos = self.buf.len();
332 true
333 }
334 }
335
336 pub fn move_home(&mut self) -> bool {
338 let start = self.start_of_line();
339 if self.pos > start {
340 self.pos = start;
341 true
342 } else {
343 false
344 }
345 }
346
347 pub fn move_end(&mut self) -> bool {
349 let end = self.end_of_line();
350 if self.pos == end {
351 false
352 } else {
353 self.pos = end;
354 true
355 }
356 }
357
358 #[must_use]
360 pub fn is_end_of_input(&self) -> bool {
361 self.pos >= self.buf.trim_end().len()
362 }
363
364 pub fn delete<D: DeleteListener>(&mut self, n: RepeatCount, dl: &mut D) -> Option<String> {
369 match self.next_pos(n) {
370 Some(pos) => {
371 let start = self.pos;
372 let chars = self
373 .drain(start..pos, Direction::Forward, dl)
374 .collect::<String>();
375 Some(chars)
376 }
377 None => None,
378 }
379 }
380
381 pub fn backspace<D: DeleteListener>(&mut self, n: RepeatCount, dl: &mut D) -> bool {
384 match self.prev_pos(n) {
385 Some(pos) => {
386 let end = self.pos;
387 self.drain(pos..end, Direction::Backward, dl);
388 self.pos = pos;
389 true
390 }
391 None => false,
392 }
393 }
394
395 pub fn kill_line<D: DeleteListener>(&mut self, dl: &mut D) -> bool {
397 if !self.buf.is_empty() && self.pos < self.buf.len() {
398 let start = self.pos;
399 let end = self.end_of_line();
400 if start == end {
401 self.delete(1, dl);
402 } else {
403 self.drain(start..end, Direction::Forward, dl);
404 }
405 true
406 } else {
407 false
408 }
409 }
410
411 pub fn kill_buffer<D: DeleteListener>(&mut self, dl: &mut D) -> bool {
413 if !self.buf.is_empty() && self.pos < self.buf.len() {
414 let start = self.pos;
415 let end = self.buf.len();
416 self.drain(start..end, Direction::Forward, dl);
417 true
418 } else {
419 false
420 }
421 }
422
423 pub fn discard_line<D: DeleteListener>(&mut self, dl: &mut D) -> bool {
425 if self.pos > 0 && !self.buf.is_empty() {
426 let start = self.start_of_line();
427 let end = self.pos;
428 if end == start {
429 self.backspace(1, dl)
430 } else {
431 self.drain(start..end, Direction::Backward, dl);
432 self.pos = start;
433 true
434 }
435 } else {
436 false
437 }
438 }
439
440 pub fn discard_buffer<D: DeleteListener>(&mut self, dl: &mut D) -> bool {
442 if self.pos > 0 && !self.buf.is_empty() {
443 let end = self.pos;
444 self.drain(0..end, Direction::Backward, dl);
445 self.pos = 0;
446 true
447 } else {
448 false
449 }
450 }
451
452 pub fn transpose_chars<C: ChangeListener>(&mut self, cl: &mut C) -> bool {
454 if self.pos == 0 || self.buf.graphemes(true).count() < 2 {
455 return false;
456 }
457 if self.pos == self.buf.len() {
458 self.move_backward(1);
459 }
460 let chars = self.delete(1, cl).unwrap();
461 self.move_backward(1);
462 self.yank(&chars, 1, cl);
463 self.move_forward(1);
464 true
465 }
466
467 fn prev_word_pos(&self, pos: usize, word_def: Word, n: RepeatCount) -> Option<usize> {
469 if pos == 0 {
470 return None;
471 }
472 let mut sow = 0;
473 let mut gis = self.buf[..pos].grapheme_indices(true).rev();
474 'outer: for _ in 0..n {
475 sow = 0;
476 let mut gj = gis.next();
477 'inner: loop {
478 if let Some((j, y)) = gj {
479 let gi = gis.next();
480 if let Some((_, x)) = gi {
481 if is_start_of_word(word_def, x, y) {
482 sow = j;
483 break 'inner;
484 }
485 gj = gi;
486 } else {
487 break 'outer;
488 }
489 } else {
490 break 'outer;
491 }
492 }
493 }
494 Some(sow)
495 }
496
497 pub fn move_to_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
499 if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
500 self.pos = pos;
501 true
502 } else {
503 false
504 }
505 }
506
507 pub fn delete_prev_word<D: DeleteListener>(
510 &mut self,
511 word_def: Word,
512 n: RepeatCount,
513 dl: &mut D,
514 ) -> bool {
515 if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
516 let end = self.pos;
517 self.drain(pos..end, Direction::Backward, dl);
518 self.pos = pos;
519 true
520 } else {
521 false
522 }
523 }
524
525 fn next_word_pos(&self, pos: usize, at: At, word_def: Word, n: RepeatCount) -> Option<usize> {
526 if pos == self.buf.len() {
527 return None;
528 }
529 let mut wp = 0;
530 let mut gis = self.buf[pos..].grapheme_indices(true);
531 let mut gi = if at == At::BeforeEnd {
532 gis.next()
534 } else {
535 None
536 };
537 'outer: for _ in 0..n {
538 wp = 0;
539 gi = gis.next();
540 'inner: loop {
541 if let Some((i, x)) = gi {
542 let gj = gis.next();
543 if let Some((j, y)) = gj {
544 if at == At::Start && is_start_of_word(word_def, x, y) {
545 wp = j;
546 break 'inner;
547 } else if at != At::Start && is_end_of_word(word_def, x, y) {
548 if word_def == Word::Emacs || at == At::AfterEnd {
549 wp = j;
550 } else {
551 wp = i;
552 }
553 break 'inner;
554 }
555 gi = gj;
556 } else {
557 break 'outer;
558 }
559 } else {
560 break 'outer;
561 }
562 }
563 }
564 if wp == 0 {
565 if word_def == Word::Emacs || at == At::AfterEnd {
566 Some(self.buf.len())
567 } else {
568 match gi {
569 Some((i, _)) if i != 0 => Some(i + pos),
570 _ => None,
571 }
572 }
573 } else {
574 Some(wp + pos)
575 }
576 }
577
578 pub fn move_to_next_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
580 if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
581 self.pos = pos;
582 true
583 } else {
584 false
585 }
586 }
587
588 pub fn move_to_line_up(&mut self, n: RepeatCount) -> bool {
590 match self.buf[..self.pos].rfind('\n') {
591 Some(off) => {
592 let column = self.buf[off + 1..self.pos].graphemes(true).count();
593
594 let mut dest_start = self.buf[..off].rfind('\n').map_or(0, |n| n + 1);
595 let mut dest_end = off;
596 for _ in 1..n {
597 if dest_start == 0 {
598 break;
599 }
600 dest_end = dest_start - 1;
601 dest_start = self.buf[..dest_end].rfind('\n').map_or(0, |n| n + 1);
602 }
603 let gidx = self.buf[dest_start..dest_end]
604 .grapheme_indices(true)
605 .nth(column);
606
607 self.pos = gidx.map_or(off, |(idx, _)| dest_start + idx); true
609 }
610 None => false,
611 }
612 }
613
614 fn n_lines_up(&self, n: RepeatCount) -> Option<(usize, usize)> {
618 let mut start = if let Some(off) = self.buf[..self.pos].rfind('\n') {
619 off + 1
620 } else {
621 return None;
622 };
623 let end = self.buf[self.pos..]
624 .find('\n')
625 .map_or_else(|| self.buf.len(), |x| self.pos + x + 1);
626 for _ in 0..n {
627 if let Some(off) = self.buf[..start - 1].rfind('\n') {
628 start = off + 1;
629 } else {
630 start = 0;
631 break;
632 }
633 }
634 Some((start, end))
635 }
636
637 fn n_lines_down(&self, n: RepeatCount) -> Option<(usize, usize)> {
641 let mut end = if let Some(off) = self.buf[self.pos..].find('\n') {
642 self.pos + off + 1
643 } else {
644 return None;
645 };
646 let start = self.buf[..self.pos].rfind('\n').unwrap_or(0);
647 for _ in 0..n {
648 if let Some(off) = self.buf[end..].find('\n') {
649 end = end + off + 1;
650 } else {
651 end = self.buf.len();
652 break;
653 };
654 }
655 Some((start, end))
656 }
657
658 pub fn move_to_line_down(&mut self, n: RepeatCount) -> bool {
660 match self.buf[self.pos..].find('\n') {
661 Some(off) => {
662 let line_start = self.buf[..self.pos].rfind('\n').map_or(0, |n| n + 1);
663 let column = self.buf[line_start..self.pos].graphemes(true).count();
664 let mut dest_start = self.pos + off + 1;
665 let mut dest_end = self.buf[dest_start..]
666 .find('\n')
667 .map_or_else(|| self.buf.len(), |v| dest_start + v);
668 for _ in 1..n {
669 if dest_end == self.buf.len() {
670 break;
671 }
672 dest_start = dest_end + 1;
673 dest_end = self.buf[dest_start..]
674 .find('\n')
675 .map_or_else(|| self.buf.len(), |v| dest_start + v);
676 }
677 self.pos = self.buf[dest_start..dest_end]
678 .grapheme_indices(true)
679 .nth(column)
680 .map_or(dest_end, |(idx, _)| dest_start + idx); debug_assert!(self.pos <= self.buf.len());
682 true
683 }
684 None => false,
685 }
686 }
687
688 fn search_char_pos(&self, cs: CharSearch, n: RepeatCount) -> Option<usize> {
689 let mut shift = 0;
690 let search_result = match cs {
691 CharSearch::Backward(c) | CharSearch::BackwardAfter(c) => self.buf[..self.pos]
692 .char_indices()
693 .rev()
694 .filter(|&(_, ch)| ch == c)
695 .take(n)
696 .last()
697 .map(|(i, _)| i),
698 CharSearch::Forward(c) | CharSearch::ForwardBefore(c) => {
699 if let Some(cc) = self.grapheme_at_cursor() {
700 shift = self.pos + cc.len();
701 if shift < self.buf.len() {
702 self.buf[shift..]
703 .char_indices()
704 .filter(|&(_, ch)| ch == c)
705 .take(n)
706 .last()
707 .map(|(i, _)| i)
708 } else {
709 None
710 }
711 } else {
712 None
713 }
714 }
715 };
716 search_result.map(|pos| match cs {
717 CharSearch::Backward(_) => pos,
718 CharSearch::BackwardAfter(c) => pos + c.len_utf8(),
719 CharSearch::Forward(_) => shift + pos,
720 CharSearch::ForwardBefore(_) => {
721 shift + pos
722 - self.buf[..shift + pos]
723 .chars()
724 .next_back()
725 .unwrap()
726 .len_utf8()
727 }
728 })
729 }
730
731 pub fn move_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
734 if let Some(pos) = self.search_char_pos(cs, n) {
735 self.pos = pos;
736 true
737 } else {
738 false
739 }
740 }
741
742 pub fn delete_word<D: DeleteListener>(
745 &mut self,
746 at: At,
747 word_def: Word,
748 n: RepeatCount,
749 dl: &mut D,
750 ) -> bool {
751 if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
752 let start = self.pos;
753 self.drain(start..pos, Direction::Forward, dl);
754 true
755 } else {
756 false
757 }
758 }
759
760 pub fn delete_to<D: DeleteListener>(
762 &mut self,
763 cs: CharSearch,
764 n: RepeatCount,
765 dl: &mut D,
766 ) -> bool {
767 let search_result = match cs {
768 CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
769 _ => self.search_char_pos(cs, n),
770 };
771 if let Some(pos) = search_result {
772 match cs {
773 CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
774 let end = self.pos;
775 self.pos = pos;
776 self.drain(pos..end, Direction::Backward, dl);
777 }
778 CharSearch::ForwardBefore(_) => {
779 let start = self.pos;
780 self.drain(start..pos, Direction::Forward, dl);
781 }
782 CharSearch::Forward(c) => {
783 let start = self.pos;
784 self.drain(start..pos + c.len_utf8(), Direction::Forward, dl);
785 }
786 };
787 true
788 } else {
789 false
790 }
791 }
792
793 fn skip_whitespace(&self) -> Option<usize> {
794 if self.pos == self.buf.len() {
795 return None;
796 }
797 self.buf[self.pos..]
798 .grapheme_indices(true)
799 .find_map(|(i, ch)| {
800 if ch.chars().all(char::is_alphanumeric) {
801 Some(i)
802 } else {
803 None
804 }
805 })
806 .map(|i| i + self.pos)
807 }
808
809 pub fn edit_word<C: ChangeListener>(&mut self, a: WordAction, cl: &mut C) -> bool {
811 if let Some(start) = self.skip_whitespace() {
812 if let Some(end) = self.next_word_pos(start, At::AfterEnd, Word::Emacs, 1) {
813 if start == end {
814 return false;
815 }
816 let word = self
817 .drain(start..end, Direction::default(), cl)
818 .collect::<String>();
819 let result = match a {
820 WordAction::Capitalize => {
821 let ch = word.graphemes(true).next().unwrap();
822 let cap = ch.to_uppercase();
823 cap + &word[ch.len()..].to_lowercase()
824 }
825 WordAction::Lowercase => word.to_lowercase(),
826 WordAction::Uppercase => word.to_uppercase(),
827 };
828 self.insert_str(start, &result, cl);
829 self.pos = start + result.len();
830 return true;
831 }
832 }
833 false
834 }
835
836 pub fn transpose_words<C: ChangeListener>(&mut self, n: RepeatCount, cl: &mut C) -> bool {
838 let word_def = Word::Emacs;
839 self.move_to_next_word(At::AfterEnd, word_def, n);
840 let w2_end = self.pos;
841 self.move_to_prev_word(word_def, 1);
842 let w2_beg = self.pos;
843 self.move_to_prev_word(word_def, n);
844 let w1_beg = self.pos;
845 self.move_to_next_word(At::AfterEnd, word_def, 1);
846 let w1_end = self.pos;
847 if w1_beg == w2_beg || w2_beg < w1_end {
848 return false;
849 }
850
851 let w1 = self.buf[w1_beg..w1_end].to_owned();
852
853 let w2 = self
854 .drain(w2_beg..w2_end, Direction::default(), cl)
855 .collect::<String>();
856 self.insert_str(w2_beg, &w1, cl);
857
858 self.drain(w1_beg..w1_end, Direction::default(), cl);
859 self.insert_str(w1_beg, &w2, cl);
860
861 self.pos = w2_end;
862 true
863 }
864
865 pub fn replace<C: ChangeListener>(&mut self, range: Range<usize>, text: &str, cl: &mut C) {
868 let start = range.start;
869 cl.replace(start, self.buf.index(range.clone()), text);
870 self.buf.drain(range);
871 if start == self.buf.len() {
872 self.buf.push_str(text);
873 } else {
874 self.buf.insert_str(start, text);
875 }
876 self.pos = start + text.len();
877 }
878
879 pub fn insert_str<C: ChangeListener>(&mut self, idx: usize, s: &str, cl: &mut C) -> bool {
882 cl.insert_str(idx, s);
883 if idx == self.buf.len() {
884 self.buf.push_str(s);
885 true
886 } else {
887 self.buf.insert_str(idx, s);
888 false
889 }
890 }
891
892 pub fn delete_range<D: DeleteListener>(&mut self, range: Range<usize>, dl: &mut D) {
894 self.set_pos(range.start);
895 self.drain(range, Direction::default(), dl);
896 }
897
898 fn drain<D: DeleteListener>(
899 &mut self,
900 range: Range<usize>,
901 dir: Direction,
902 dl: &mut D,
903 ) -> Drain<'_> {
904 dl.delete(range.start, &self.buf[range.start..range.end], dir);
905 self.buf.drain(range)
906 }
907
908 #[must_use]
911 pub fn copy(&self, mvt: &Movement) -> Option<String> {
912 if self.is_empty() {
913 return None;
914 }
915 match *mvt {
916 Movement::WholeLine => {
917 let start = self.start_of_line();
918 let end = self.end_of_line();
919 if start == end {
920 None
921 } else {
922 Some(self.buf[start..self.pos].to_owned())
923 }
924 }
925 Movement::BeginningOfLine => {
926 let start = self.start_of_line();
927 if self.pos == start {
928 None
929 } else {
930 Some(self.buf[start..self.pos].to_owned())
931 }
932 }
933 Movement::ViFirstPrint => {
934 if self.pos == 0 {
935 None
936 } else {
937 self.next_word_pos(0, At::Start, Word::Big, 1)
938 .map(|pos| self.buf[pos..self.pos].to_owned())
939 }
940 }
941 Movement::EndOfLine => {
942 let end = self.end_of_line();
943 if self.pos == end {
944 None
945 } else {
946 Some(self.buf[self.pos..end].to_owned())
947 }
948 }
949 Movement::EndOfBuffer => {
950 if self.pos == self.buf.len() {
951 None
952 } else {
953 Some(self.buf[self.pos..].to_owned())
954 }
955 }
956 Movement::WholeBuffer => {
957 if self.buf.is_empty() {
958 None
959 } else {
960 Some(self.buf.clone())
961 }
962 }
963 Movement::BeginningOfBuffer => {
964 if self.pos == 0 {
965 None
966 } else {
967 Some(self.buf[..self.pos].to_owned())
968 }
969 }
970 Movement::BackwardWord(n, word_def) => self
971 .prev_word_pos(self.pos, word_def, n)
972 .map(|pos| self.buf[pos..self.pos].to_owned()),
973 Movement::ForwardWord(n, at, word_def) => self
974 .next_word_pos(self.pos, at, word_def, n)
975 .map(|pos| self.buf[self.pos..pos].to_owned()),
976 Movement::ViCharSearch(n, cs) => {
977 let search_result = match cs {
978 CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
979 _ => self.search_char_pos(cs, n),
980 };
981 search_result.map(|pos| match cs {
982 CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
983 self.buf[pos..self.pos].to_owned()
984 }
985 CharSearch::ForwardBefore(_) => self.buf[self.pos..pos].to_owned(),
986 CharSearch::Forward(c) => self.buf[self.pos..pos + c.len_utf8()].to_owned(),
987 })
988 }
989 Movement::BackwardChar(n) => self
990 .prev_pos(n)
991 .map(|pos| self.buf[pos..self.pos].to_owned()),
992 Movement::ForwardChar(n) => self
993 .next_pos(n)
994 .map(|pos| self.buf[self.pos..pos].to_owned()),
995 Movement::LineUp(n) => {
996 if let Some((start, end)) = self.n_lines_up(n) {
997 Some(self.buf[start..end].to_owned())
998 } else {
999 None
1000 }
1001 }
1002 Movement::LineDown(n) => {
1003 if let Some((start, end)) = self.n_lines_down(n) {
1004 Some(self.buf[start..end].to_owned())
1005 } else {
1006 None
1007 }
1008 }
1009 }
1010 }
1011
1012 pub fn kill<D: DeleteListener>(&mut self, mvt: &Movement, dl: &mut D) -> bool {
1014 let notify = !matches!(*mvt, Movement::ForwardChar(_) | Movement::BackwardChar(_));
1015 if notify {
1016 dl.start_killing();
1017 }
1018 let killed = match *mvt {
1019 Movement::ForwardChar(n) => {
1020 self.delete(n, dl).is_some()
1022 }
1023 Movement::BackwardChar(n) => {
1024 self.backspace(n, dl)
1026 }
1027 Movement::EndOfLine => {
1028 self.kill_line(dl)
1030 }
1031 Movement::WholeLine => {
1032 self.move_home();
1033 self.kill_line(dl)
1034 }
1035 Movement::BeginningOfLine => {
1036 self.discard_line(dl)
1038 }
1039 Movement::BackwardWord(n, word_def) => {
1040 self.delete_prev_word(word_def, n, dl)
1042 }
1043 Movement::ForwardWord(n, at, word_def) => {
1044 self.delete_word(at, word_def, n, dl)
1046 }
1047 Movement::ViCharSearch(n, cs) => self.delete_to(cs, n, dl),
1048 Movement::LineUp(n) => {
1049 if let Some((start, end)) = self.n_lines_up(n) {
1050 self.delete_range(start..end, dl);
1051 true
1052 } else {
1053 false
1054 }
1055 }
1056 Movement::LineDown(n) => {
1057 if let Some((start, end)) = self.n_lines_down(n) {
1058 self.delete_range(start..end, dl);
1059 true
1060 } else {
1061 false
1062 }
1063 }
1064 Movement::ViFirstPrint => {
1065 false }
1067 Movement::EndOfBuffer => {
1068 self.kill_buffer(dl)
1070 }
1071 Movement::BeginningOfBuffer => {
1072 self.discard_buffer(dl)
1074 }
1075 Movement::WholeBuffer => {
1076 self.move_buffer_start();
1077 self.kill_buffer(dl)
1078 }
1079 };
1080 if notify {
1081 dl.stop_killing();
1082 }
1083 killed
1084 }
1085
1086 pub fn indent<C: ChangeListener>(
1088 &mut self,
1089 mvt: &Movement,
1090 amount: usize,
1091 dedent: bool,
1092 cl: &mut C,
1093 ) -> bool {
1094 let pair = match *mvt {
1095 Movement::WholeLine
1097 | Movement::BeginningOfLine
1098 | Movement::ViFirstPrint
1099 | Movement::EndOfLine
1100 | Movement::BackwardChar(..)
1101 | Movement::ForwardChar(..)
1102 | Movement::ViCharSearch(..) => Some((self.pos, self.pos)),
1103 Movement::EndOfBuffer => Some((self.pos, self.buf.len())),
1104 Movement::WholeBuffer => Some((0, self.buf.len())),
1105 Movement::BeginningOfBuffer => Some((0, self.pos)),
1106 Movement::BackwardWord(n, word_def) => self
1107 .prev_word_pos(self.pos, word_def, n)
1108 .map(|pos| (pos, self.pos)),
1109 Movement::ForwardWord(n, at, word_def) => self
1110 .next_word_pos(self.pos, at, word_def, n)
1111 .map(|pos| (self.pos, pos)),
1112 Movement::LineUp(n) => self.n_lines_up(n),
1113 Movement::LineDown(n) => self.n_lines_down(n),
1114 };
1115 let (start, end) = pair.unwrap_or((self.pos, self.pos));
1116 let start = self.buf[..start].rfind('\n').map_or(0, |pos| pos + 1);
1117 let end = self.buf[end..]
1118 .rfind('\n')
1119 .map_or_else(|| self.buf.len(), |pos| end + pos);
1120 let mut index = start;
1121 if dedent {
1122 #[allow(clippy::unnecessary_to_owned)]
1123 for line in self.buf[start..end].to_string().split('\n') {
1124 let max = line.len() - line.trim_start().len();
1125 let deleting = min(max, amount);
1126 self.drain(index..index + deleting, Direction::default(), cl);
1127 if self.pos >= index {
1128 if self.pos.saturating_sub(index) < deleting {
1129 self.pos = index;
1131 } else {
1132 self.pos -= deleting;
1133 }
1134 }
1135 index += line.len() + 1 - deleting;
1136 }
1137 } else {
1138 #[allow(clippy::unnecessary_to_owned)]
1139 for line in self.buf[start..end].to_string().split('\n') {
1140 for off in (0..amount).step_by(INDENT.len()) {
1141 self.insert_str(index, &INDENT[..min(amount - off, INDENT.len())], cl);
1142 }
1143 if self.pos >= index {
1144 self.pos += amount;
1145 }
1146 index += amount + line.len() + 1;
1147 }
1148 }
1149 true
1150 }
1151}
1152
1153impl Deref for LineBuffer {
1154 type Target = str;
1155
1156 fn deref(&self) -> &str {
1157 self.as_str()
1158 }
1159}
1160
1161fn is_start_of_word(word_def: Word, previous: &str, grapheme: &str) -> bool {
1162 (!is_word_char(word_def, previous) && is_word_char(word_def, grapheme))
1163 || (word_def == Word::Vi && !is_other_char(previous) && is_other_char(grapheme))
1164}
1165fn is_end_of_word(word_def: Word, grapheme: &str, next: &str) -> bool {
1166 (!is_word_char(word_def, next) && is_word_char(word_def, grapheme))
1167 || (word_def == Word::Vi && !is_other_char(next) && is_other_char(grapheme))
1168}
1169
1170fn is_word_char(word_def: Word, grapheme: &str) -> bool {
1171 match word_def {
1172 Word::Emacs => grapheme.chars().all(char::is_alphanumeric),
1173 Word::Vi => is_vi_word_char(grapheme),
1174 Word::Big => !grapheme.chars().any(char::is_whitespace),
1175 }
1176}
1177fn is_vi_word_char(grapheme: &str) -> bool {
1178 grapheme.chars().all(char::is_alphanumeric) || grapheme == "_"
1179}
1180fn is_other_char(grapheme: &str) -> bool {
1181 !(grapheme.chars().any(char::is_whitespace) || is_vi_word_char(grapheme))
1182}
1183
1184#[cfg(test)]
1185mod test {
1186 use super::{
1187 ChangeListener, DeleteListener, Direction, LineBuffer, NoListener, WordAction, MAX_LINE,
1188 };
1189 use crate::keymap::{At, CharSearch, Word};
1190
1191 struct Listener {
1192 deleted_str: Option<String>,
1193 }
1194
1195 impl Listener {
1196 fn new() -> Listener {
1197 Listener { deleted_str: None }
1198 }
1199
1200 fn assert_deleted_str_eq(&self, expected: &str) {
1201 let actual = self.deleted_str.as_ref().expect("no deleted string");
1202 assert_eq!(expected, actual)
1203 }
1204 }
1205
1206 impl DeleteListener for Listener {
1207 fn delete(&mut self, _: usize, string: &str, _: Direction) {
1208 self.deleted_str = Some(string.to_owned());
1209 }
1210 }
1211 impl ChangeListener for Listener {
1212 fn insert_char(&mut self, _: usize, _: char) {}
1213
1214 fn insert_str(&mut self, _: usize, _: &str) {}
1215
1216 fn replace(&mut self, _: usize, _: &str, _: &str) {}
1217 }
1218
1219 #[test]
1220 fn next_pos() {
1221 let s = LineBuffer::init("ö̲g̈", 0);
1222 assert_eq!(7, s.len());
1223 let pos = s.next_pos(1);
1224 assert_eq!(Some(4), pos);
1225
1226 let s = LineBuffer::init("ö̲g̈", 4);
1227 let pos = s.next_pos(1);
1228 assert_eq!(Some(7), pos);
1229 }
1230
1231 #[test]
1232 fn prev_pos() {
1233 let s = LineBuffer::init("ö̲g̈", 4);
1234 assert_eq!(7, s.len());
1235 let pos = s.prev_pos(1);
1236 assert_eq!(Some(0), pos);
1237
1238 let s = LineBuffer::init("ö̲g̈", 7);
1239 let pos = s.prev_pos(1);
1240 assert_eq!(Some(4), pos);
1241 }
1242
1243 #[test]
1244 fn insert() {
1245 let mut s = LineBuffer::with_capacity(MAX_LINE);
1246 let push = s.insert('α', 1, &mut NoListener).unwrap();
1247 assert_eq!("α", s.buf);
1248 assert_eq!(2, s.pos);
1249 assert!(push);
1250
1251 let push = s.insert('ß', 1, &mut NoListener).unwrap();
1252 assert_eq!("αß", s.buf);
1253 assert_eq!(4, s.pos);
1254 assert!(push);
1255
1256 s.pos = 0;
1257 let push = s.insert('γ', 1, &mut NoListener).unwrap();
1258 assert_eq!("γαß", s.buf);
1259 assert_eq!(2, s.pos);
1260 assert!(!push);
1261 }
1262
1263 #[test]
1264 fn yank_after() {
1265 let mut s = LineBuffer::init("αß", 2);
1266 s.move_forward(1);
1267 let ok = s.yank("γδε", 1, &mut NoListener);
1268 assert_eq!(Some(true), ok);
1269 assert_eq!("αßγδε", s.buf);
1270 assert_eq!(10, s.pos);
1271 }
1272
1273 #[test]
1274 fn yank_before() {
1275 let mut s = LineBuffer::init("αε", 2);
1276 let ok = s.yank("ßγδ", 1, &mut NoListener);
1277 assert_eq!(Some(false), ok);
1278 assert_eq!("αßγδε", s.buf);
1279 assert_eq!(8, s.pos);
1280 }
1281
1282 #[test]
1283 fn moves() {
1284 let mut s = LineBuffer::init("αß", 4);
1285 let ok = s.move_backward(1);
1286 assert_eq!("αß", s.buf);
1287 assert_eq!(2, s.pos);
1288 assert!(ok);
1289
1290 let ok = s.move_forward(1);
1291 assert_eq!("αß", s.buf);
1292 assert_eq!(4, s.pos);
1293 assert!(ok);
1294
1295 let ok = s.move_home();
1296 assert_eq!("αß", s.buf);
1297 assert_eq!(0, s.pos);
1298 assert!(ok);
1299
1300 let ok = s.move_end();
1301 assert_eq!("αß", s.buf);
1302 assert_eq!(4, s.pos);
1303 assert!(ok);
1304 }
1305
1306 #[test]
1307 fn move_home_end_multiline() {
1308 let text = "αa\nsdf ßc\nasdf";
1309 let mut s = LineBuffer::init(text, 7);
1310 let ok = s.move_home();
1311 assert_eq!(text, s.buf);
1312 assert_eq!(4, s.pos);
1313 assert!(ok);
1314
1315 let ok = s.move_home();
1316 assert_eq!(text, s.buf);
1317 assert_eq!(4, s.pos);
1318 assert!(!ok);
1319
1320 let ok = s.move_end();
1321 assert_eq!(text, s.buf);
1322 assert_eq!(11, s.pos);
1323 assert!(ok);
1324
1325 let ok = s.move_end();
1326 assert_eq!(text, s.buf);
1327 assert_eq!(11, s.pos);
1328 assert!(!ok);
1329 }
1330
1331 #[test]
1332 fn move_buffer_multiline() {
1333 let text = "αa\nsdf ßc\nasdf";
1334 let mut s = LineBuffer::init(text, 7);
1335 let ok = s.move_buffer_start();
1336 assert_eq!(text, s.buf);
1337 assert_eq!(0, s.pos);
1338 assert!(ok);
1339
1340 let ok = s.move_buffer_start();
1341 assert_eq!(text, s.buf);
1342 assert_eq!(0, s.pos);
1343 assert!(!ok);
1344
1345 let ok = s.move_buffer_end();
1346 assert_eq!(text, s.buf);
1347 assert_eq!(text.len(), s.pos);
1348 assert!(ok);
1349
1350 let ok = s.move_buffer_end();
1351 assert_eq!(text, s.buf);
1352 assert_eq!(text.len(), s.pos);
1353 assert!(!ok);
1354 }
1355
1356 #[test]
1357 fn move_grapheme() {
1358 let mut s = LineBuffer::init("ag̈", 4);
1359 assert_eq!(4, s.len());
1360 let ok = s.move_backward(1);
1361 assert!(ok);
1362 assert_eq!(1, s.pos);
1363
1364 let ok = s.move_forward(1);
1365 assert!(ok);
1366 assert_eq!(4, s.pos);
1367 }
1368
1369 #[test]
1370 fn delete() {
1371 let mut cl = Listener::new();
1372 let mut s = LineBuffer::init("αß", 2);
1373 let chars = s.delete(1, &mut cl);
1374 assert_eq!("α", s.buf);
1375 assert_eq!(2, s.pos);
1376 assert_eq!(Some("ß".to_owned()), chars);
1377
1378 let ok = s.backspace(1, &mut cl);
1379 assert_eq!("", s.buf);
1380 assert_eq!(0, s.pos);
1381 assert!(ok);
1382 cl.assert_deleted_str_eq("α");
1383 }
1384
1385 #[test]
1386 fn kill() {
1387 let mut cl = Listener::new();
1388 let mut s = LineBuffer::init("αßγδε", 6);
1389 let ok = s.kill_line(&mut cl);
1390 assert_eq!("αßγ", s.buf);
1391 assert_eq!(6, s.pos);
1392 assert!(ok);
1393 cl.assert_deleted_str_eq("δε");
1394
1395 s.pos = 4;
1396 let ok = s.discard_line(&mut cl);
1397 assert_eq!("γ", s.buf);
1398 assert_eq!(0, s.pos);
1399 assert!(ok);
1400 cl.assert_deleted_str_eq("αß");
1401 }
1402
1403 #[test]
1404 fn kill_multiline() {
1405 let mut cl = Listener::new();
1406 let mut s = LineBuffer::init("αß\nγδ 12\nε f4", 7);
1407
1408 let ok = s.kill_line(&mut cl);
1409 assert_eq!("αß\nγ\nε f4", s.buf);
1410 assert_eq!(7, s.pos);
1411 assert!(ok);
1412 cl.assert_deleted_str_eq("δ 12");
1413
1414 let ok = s.kill_line(&mut cl);
1415 assert_eq!("αß\nγε f4", s.buf);
1416 assert_eq!(7, s.pos);
1417 assert!(ok);
1418 cl.assert_deleted_str_eq("\n");
1419
1420 let ok = s.kill_line(&mut cl);
1421 assert_eq!("αß\nγ", s.buf);
1422 assert_eq!(7, s.pos);
1423 assert!(ok);
1424 cl.assert_deleted_str_eq("ε f4");
1425
1426 let ok = s.kill_line(&mut cl);
1427 assert_eq!(7, s.pos);
1428 assert!(!ok);
1429 }
1430
1431 #[test]
1432 fn discard_multiline() {
1433 let mut cl = Listener::new();
1434 let mut s = LineBuffer::init("αß\nc γδε", 9);
1435
1436 let ok = s.discard_line(&mut cl);
1437 assert_eq!("αß\nδε", s.buf);
1438 assert_eq!(5, s.pos);
1439 assert!(ok);
1440 cl.assert_deleted_str_eq("c γ");
1441
1442 let ok = s.discard_line(&mut cl);
1443 assert_eq!("αßδε", s.buf);
1444 assert_eq!(4, s.pos);
1445 assert!(ok);
1446 cl.assert_deleted_str_eq("\n");
1447
1448 let ok = s.discard_line(&mut cl);
1449 assert_eq!("δε", s.buf);
1450 assert_eq!(0, s.pos);
1451 assert!(ok);
1452 cl.assert_deleted_str_eq("αß");
1453
1454 let ok = s.discard_line(&mut cl);
1455 assert_eq!(0, s.pos);
1456 assert!(!ok);
1457 }
1458
1459 #[test]
1460 fn transpose() {
1461 let mut s = LineBuffer::init("aßc", 1);
1462 let ok = s.transpose_chars(&mut NoListener);
1463 assert_eq!("ßac", s.buf);
1464 assert_eq!(3, s.pos);
1465 assert!(ok);
1466
1467 s.buf = String::from("aßc");
1468 s.pos = 3;
1469 let ok = s.transpose_chars(&mut NoListener);
1470 assert_eq!("acß", s.buf);
1471 assert_eq!(4, s.pos);
1472 assert!(ok);
1473
1474 s.buf = String::from("aßc");
1475 s.pos = 4;
1476 let ok = s.transpose_chars(&mut NoListener);
1477 assert_eq!("acß", s.buf);
1478 assert_eq!(4, s.pos);
1479 assert!(ok);
1480 }
1481
1482 #[test]
1483 fn move_to_prev_word() {
1484 let mut s = LineBuffer::init("a ß c", 6); let ok = s.move_to_prev_word(Word::Emacs, 1);
1486 assert_eq!("a ß c", s.buf);
1487 assert_eq!(2, s.pos); assert!(ok);
1489
1490 assert!(s.move_end()); assert_eq!(7, s.pos);
1492 let ok = s.move_to_prev_word(Word::Emacs, 1);
1493 assert!(ok);
1494 assert_eq!(6, s.pos); let ok = s.move_to_prev_word(Word::Emacs, 2);
1497 assert!(ok);
1498 assert_eq!(0, s.pos);
1499 }
1500
1501 #[test]
1502 fn move_to_prev_vi_word() {
1503 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19);
1504 let ok = s.move_to_prev_word(Word::Vi, 1);
1505 assert!(ok);
1506 assert_eq!(17, s.pos);
1507 let ok = s.move_to_prev_word(Word::Vi, 1);
1508 assert!(ok);
1509 assert_eq!(15, s.pos);
1510 let ok = s.move_to_prev_word(Word::Vi, 1);
1511 assert!(ok);
1512 assert_eq!(12, s.pos);
1513 let ok = s.move_to_prev_word(Word::Vi, 1);
1514 assert!(ok);
1515 assert_eq!(11, s.pos);
1516 let ok = s.move_to_prev_word(Word::Vi, 1);
1517 assert!(ok);
1518 assert_eq!(7, s.pos);
1519 let ok = s.move_to_prev_word(Word::Vi, 1);
1520 assert!(ok);
1521 assert_eq!(6, s.pos);
1522 let ok = s.move_to_prev_word(Word::Vi, 1);
1523 assert!(ok);
1524 assert_eq!(0, s.pos);
1525 let ok = s.move_to_prev_word(Word::Vi, 1);
1526 assert!(!ok);
1527 }
1528
1529 #[test]
1530 fn move_to_prev_big_word() {
1531 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19);
1532 let ok = s.move_to_prev_word(Word::Big, 1);
1533 assert!(ok);
1534 assert_eq!(17, s.pos);
1535 let ok = s.move_to_prev_word(Word::Big, 1);
1536 assert!(ok);
1537 assert_eq!(6, s.pos);
1538 let ok = s.move_to_prev_word(Word::Big, 1);
1539 assert!(ok);
1540 assert_eq!(0, s.pos);
1541 let ok = s.move_to_prev_word(Word::Big, 1);
1542 assert!(!ok);
1543 }
1544
1545 #[test]
1546 fn move_to_forward() {
1547 let mut s = LineBuffer::init("αßγδε", 2);
1548 let ok = s.move_to(CharSearch::ForwardBefore('ε'), 1);
1549 assert!(ok);
1550 assert_eq!(6, s.pos);
1551
1552 let mut s = LineBuffer::init("αßγδε", 2);
1553 let ok = s.move_to(CharSearch::Forward('ε'), 1);
1554 assert!(ok);
1555 assert_eq!(8, s.pos);
1556
1557 let mut s = LineBuffer::init("αßγδε", 2);
1558 let ok = s.move_to(CharSearch::Forward('ε'), 10);
1559 assert!(ok);
1560 assert_eq!(8, s.pos);
1561 }
1562
1563 #[test]
1564 fn move_to_backward() {
1565 let mut s = LineBuffer::init("αßγδε", 8);
1566 let ok = s.move_to(CharSearch::BackwardAfter('ß'), 1);
1567 assert!(ok);
1568 assert_eq!(4, s.pos);
1569
1570 let mut s = LineBuffer::init("αßγδε", 8);
1571 let ok = s.move_to(CharSearch::Backward('ß'), 1);
1572 assert!(ok);
1573 assert_eq!(2, s.pos);
1574 }
1575
1576 #[test]
1577 fn delete_prev_word() {
1578 let mut cl = Listener::new();
1579 let mut s = LineBuffer::init("a ß c", 6);
1580 let ok = s.delete_prev_word(Word::Big, 1, &mut cl);
1581 assert_eq!("a c", s.buf);
1582 assert_eq!(2, s.pos);
1583 assert!(ok);
1584 cl.assert_deleted_str_eq("ß ");
1585 }
1586
1587 #[test]
1588 fn move_to_next_word() {
1589 let mut s = LineBuffer::init("a ß c", 1); let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1591 assert_eq!("a ß c", s.buf);
1592 assert!(ok);
1593 assert_eq!(4, s.pos); let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1596 assert!(ok);
1597 assert_eq!(7, s.pos); s.move_home();
1600 let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1601 assert!(ok);
1602 assert_eq!(1, s.pos); let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 2);
1605 assert!(ok);
1606 assert_eq!(7, s.pos); }
1608
1609 #[test]
1610 fn move_to_end_of_word() {
1611 let mut s = LineBuffer::init("a ßeta c", 1);
1612 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1613 assert_eq!("a ßeta c", s.buf);
1614 assert_eq!(6, s.pos);
1615 assert!(ok);
1616 }
1617
1618 #[test]
1619 fn move_to_end_of_vi_word() {
1620 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0);
1621 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1622 assert!(ok);
1623 assert_eq!(4, s.pos);
1624 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1625 assert!(ok);
1626 assert_eq!(6, s.pos);
1627 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1628 assert!(ok);
1629 assert_eq!(10, s.pos);
1630 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1631 assert!(ok);
1632 assert_eq!(11, s.pos);
1633 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1634 assert!(ok);
1635 assert_eq!(14, s.pos);
1636 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1637 assert!(ok);
1638 assert_eq!(15, s.pos);
1639 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1640 assert!(ok);
1641 assert_eq!(18, s.pos);
1642 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1643 assert!(!ok);
1644 }
1645
1646 #[test]
1647 fn move_to_end_of_big_word() {
1648 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0);
1649 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1650 assert!(ok);
1651 assert_eq!(4, s.pos);
1652 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1653 assert!(ok);
1654 assert_eq!(15, s.pos);
1655 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1656 assert!(ok);
1657 assert_eq!(18, s.pos);
1658 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1659 assert!(!ok);
1660 }
1661
1662 #[test]
1663 fn move_to_start_of_word() {
1664 let mut s = LineBuffer::init("a ß c", 2);
1665 let ok = s.move_to_next_word(At::Start, Word::Emacs, 1);
1666 assert_eq!("a ß c", s.buf);
1667 assert_eq!(6, s.pos);
1668 assert!(ok);
1669 }
1670
1671 #[test]
1672 fn move_to_start_of_vi_word() {
1673 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0);
1674 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1675 assert!(ok);
1676 assert_eq!(6, s.pos);
1677 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1678 assert!(ok);
1679 assert_eq!(7, s.pos);
1680 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1681 assert!(ok);
1682 assert_eq!(11, s.pos);
1683 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1684 assert!(ok);
1685 assert_eq!(12, s.pos);
1686 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1687 assert!(ok);
1688 assert_eq!(15, s.pos);
1689 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1690 assert!(ok);
1691 assert_eq!(17, s.pos);
1692 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1693 assert!(ok);
1694 assert_eq!(18, s.pos);
1695 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1696 assert!(!ok);
1697 }
1698
1699 #[test]
1700 fn move_to_start_of_big_word() {
1701 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0);
1702 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1703 assert!(ok);
1704 assert_eq!(6, s.pos);
1705 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1706 assert!(ok);
1707 assert_eq!(17, s.pos);
1708 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1709 assert!(ok);
1710 assert_eq!(18, s.pos);
1711 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1712 assert!(!ok);
1713 }
1714
1715 #[test]
1716 fn delete_word() {
1717 let mut cl = Listener::new();
1718 let mut s = LineBuffer::init("a ß c", 1);
1719 let ok = s.delete_word(At::AfterEnd, Word::Emacs, 1, &mut cl);
1720 assert_eq!("a c", s.buf);
1721 assert_eq!(1, s.pos);
1722 assert!(ok);
1723 cl.assert_deleted_str_eq(" ß");
1724
1725 let mut s = LineBuffer::init("test", 0);
1726 let ok = s.delete_word(At::AfterEnd, Word::Vi, 1, &mut cl);
1727 assert_eq!("", s.buf);
1728 assert_eq!(0, s.pos);
1729 assert!(ok);
1730 cl.assert_deleted_str_eq("test");
1731 }
1732
1733 #[test]
1734 fn delete_til_start_of_word() {
1735 let mut cl = Listener::new();
1736 let mut s = LineBuffer::init("a ß c", 2);
1737 let ok = s.delete_word(At::Start, Word::Emacs, 1, &mut cl);
1738 assert_eq!("a c", s.buf);
1739 assert_eq!(2, s.pos);
1740 assert!(ok);
1741 cl.assert_deleted_str_eq("ß ");
1742 }
1743
1744 #[test]
1745 fn delete_to_forward() {
1746 let mut cl = Listener::new();
1747 let mut s = LineBuffer::init("αßγδε", 2);
1748 let ok = s.delete_to(CharSearch::ForwardBefore('ε'), 1, &mut cl);
1749 assert!(ok);
1750 cl.assert_deleted_str_eq("ßγδ");
1751 assert_eq!("αε", s.buf);
1752 assert_eq!(2, s.pos);
1753
1754 let mut s = LineBuffer::init("αßγδε", 2);
1755 let ok = s.delete_to(CharSearch::Forward('ε'), 1, &mut cl);
1756 assert!(ok);
1757 cl.assert_deleted_str_eq("ßγδε");
1758 assert_eq!("α", s.buf);
1759 assert_eq!(2, s.pos);
1760 }
1761
1762 #[test]
1763 fn delete_to_backward() {
1764 let mut cl = Listener::new();
1765 let mut s = LineBuffer::init("αßγδε", 8);
1766 let ok = s.delete_to(CharSearch::BackwardAfter('α'), 1, &mut cl);
1767 assert!(ok);
1768 cl.assert_deleted_str_eq("ßγδ");
1769 assert_eq!("αε", s.buf);
1770 assert_eq!(2, s.pos);
1771
1772 let mut s = LineBuffer::init("αßγδε", 8);
1773 let ok = s.delete_to(CharSearch::Backward('ß'), 1, &mut cl);
1774 assert!(ok);
1775 cl.assert_deleted_str_eq("ßγδ");
1776 assert_eq!("αε", s.buf);
1777 assert_eq!(2, s.pos);
1778 }
1779
1780 #[test]
1781 fn edit_word() {
1782 let mut s = LineBuffer::init("a ßeta c", 1);
1783 assert!(s.edit_word(WordAction::Uppercase, &mut NoListener));
1784 assert_eq!("a SSETA c", s.buf);
1785 assert_eq!(7, s.pos);
1786
1787 let mut s = LineBuffer::init("a ßetA c", 1);
1788 assert!(s.edit_word(WordAction::Lowercase, &mut NoListener));
1789 assert_eq!("a ßeta c", s.buf);
1790 assert_eq!(7, s.pos);
1791
1792 let mut s = LineBuffer::init("a ßETA c", 1);
1793 assert!(s.edit_word(WordAction::Capitalize, &mut NoListener));
1794 assert_eq!("a SSeta c", s.buf);
1795 assert_eq!(7, s.pos);
1796
1797 let mut s = LineBuffer::init("test", 1);
1798 assert!(s.edit_word(WordAction::Capitalize, &mut NoListener));
1799 assert_eq!("tEst", s.buf);
1800 assert_eq!(4, s.pos);
1801 }
1802
1803 #[test]
1804 fn transpose_words() {
1805 let mut s = LineBuffer::init("ßeta / δelta__", 15);
1806 assert!(s.transpose_words(1, &mut NoListener));
1807 assert_eq!("δelta__ / ßeta", s.buf);
1808 assert_eq!(16, s.pos);
1809
1810 let mut s = LineBuffer::init("ßeta / δelta", 14);
1811 assert!(s.transpose_words(1, &mut NoListener));
1812 assert_eq!("δelta / ßeta", s.buf);
1813 assert_eq!(14, s.pos);
1814
1815 let mut s = LineBuffer::init(" / δelta", 8);
1816 assert!(!s.transpose_words(1, &mut NoListener));
1817
1818 let mut s = LineBuffer::init("ßeta / __", 9);
1819 assert!(!s.transpose_words(1, &mut NoListener));
1820 }
1821
1822 #[test]
1823 fn move_by_line() {
1824 let text = "aa123\nsdf bc\nasdf";
1825 let mut s = LineBuffer::init(text, 14);
1826 let ok = s.move_to_line_up(1);
1828 assert_eq!(7, s.pos);
1829 assert!(ok);
1830
1831 let ok = s.move_to_line_up(1);
1832 assert_eq!(1, s.pos);
1833 assert!(ok);
1834
1835 let ok = s.move_to_line_up(1);
1836 assert_eq!(1, s.pos);
1837 assert!(!ok);
1838
1839 let ok = s.move_to_line_down(1);
1841 assert_eq!(7, s.pos);
1842 assert!(ok);
1843
1844 let ok = s.move_to_line_down(1);
1845 assert_eq!(14, s.pos);
1846 assert!(ok);
1847
1848 let ok = s.move_to_line_down(1);
1849 assert_eq!(14, s.pos);
1850 assert!(!ok);
1851
1852 let ok = s.move_to_line_up(2);
1854 assert_eq!(1, s.pos);
1855 assert!(ok);
1856
1857 let ok = s.move_to_line_down(2);
1858 assert_eq!(14, s.pos);
1859 assert!(ok);
1860 }
1861
1862 #[test]
1863 fn test_send() {
1864 fn assert_send<T: Send>() {}
1865 assert_send::<LineBuffer>();
1866 }
1867
1868 #[test]
1869 fn test_sync() {
1870 fn assert_sync<T: Sync>() {}
1871 assert_sync::<LineBuffer>();
1872 }
1873}