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