1use keymap::{At, CharSearch, Movement, RepeatCount, Word};
3use std::cell::RefCell;
4use std::fmt;
5use std::iter;
6use std::ops::{Deref, Index, Range};
7use std::rc::Rc;
8use std::string::Drain;
9use std::sync::{Arc, Mutex};
10use unicode_segmentation::UnicodeSegmentation;
11
12pub(crate) static MAX_LINE: usize = 4096;
14
15#[derive(Clone, Copy)]
17pub enum WordAction {
18 CAPITALIZE,
19 LOWERCASE,
20 UPPERCASE,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub(crate) enum Direction {
26 Forward,
27 Backward,
28}
29
30impl Default for Direction {
31 fn default() -> Direction {
32 Direction::Forward
33 }
34}
35
36pub(crate) trait DeleteListener {
38 fn start_killing(&mut self);
39 fn delete(&mut self, idx: usize, string: &str, dir: Direction);
40 fn stop_killing(&mut self);
41}
42
43pub(crate) trait ChangeListener: DeleteListener {
45 fn insert_char(&mut self, idx: usize, c: char);
46 fn insert_str(&mut self, idx: usize, string: &str);
47 fn replace(&mut self, idx: usize, old: &str, new: &str);
48}
49
50pub struct LineBuffer {
54 buf: String, pos: usize, dl: Option<Arc<Mutex<DeleteListener>>>,
57 cl: Option<Rc<RefCell<ChangeListener>>>,
58}
59
60impl fmt::Debug for LineBuffer {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 f.debug_struct("LineBuffer")
63 .field("buf", &self.buf)
64 .field("pos", &self.pos)
65 .finish()
66 }
67}
68
69impl LineBuffer {
70 pub fn with_capacity(capacity: usize) -> LineBuffer {
72 LineBuffer {
73 buf: String::with_capacity(capacity),
74 pos: 0,
75 dl: None,
76 cl: None,
77 }
78 }
79
80 #[cfg(test)]
81 pub(crate) fn init(
82 line: &str,
83 pos: usize,
84 cl: Option<Rc<RefCell<ChangeListener>>>,
85 ) -> LineBuffer {
86 let mut lb = Self::with_capacity(MAX_LINE);
87 assert!(lb.insert_str(0, line));
88 lb.set_pos(pos);
89 lb.cl = cl;
90 lb
91 }
92
93 pub(crate) fn set_delete_listener(&mut self, dl: Arc<Mutex<DeleteListener>>) {
94 self.dl = Some(dl);
95 }
96 pub(crate) fn set_change_listener(&mut self, dl: Rc<RefCell<ChangeListener>>) {
97 self.cl = Some(dl);
98 }
99 pub(crate) fn remove_change_listener(&mut self) {
100 self.cl = None;
101 }
102
103 pub fn as_str(&self) -> &str {
105 &self.buf
106 }
107
108 pub fn into_string(self) -> String {
110 self.buf
111 }
112
113 pub fn pos(&self) -> usize {
115 self.pos
116 }
117 pub fn set_pos(&mut self, pos: usize) {
119 assert!(pos <= self.buf.len());
120 self.pos = pos;
121 }
122
123 pub fn len(&self) -> usize {
125 self.buf.len()
126 }
127 pub fn is_empty(&self) -> bool {
129 self.buf.is_empty()
130 }
131
132 pub fn update(&mut self, buf: &str, pos: usize) {
134 assert!(pos <= buf.len());
135 let end = self.len();
136 self.drain(0..end, Direction::default());
137 let max = self.buf.capacity();
138 if buf.len() > max {
139 self.insert_str(0, &buf[..max]);
140 if pos > max {
141 self.pos = max;
142 } else {
143 self.pos = pos;
144 }
145 } else {
146 self.insert_str(0, buf);
147 self.pos = pos;
148 }
149 }
150
151 fn grapheme_at_cursor(&self) -> Option<&str> {
153 if self.pos == self.buf.len() {
154 None
155 } else {
156 self.buf[self.pos..].graphemes(true).next()
157 }
158 }
159
160 pub fn next_pos(&self, n: RepeatCount) -> Option<usize> {
163 if self.pos == self.buf.len() {
164 return None;
165 }
166 self.buf[self.pos..]
167 .grapheme_indices(true)
168 .take(n)
169 .last()
170 .map(|(i, s)| i + self.pos + s.len())
171 }
172 fn prev_pos(&self, n: RepeatCount) -> Option<usize> {
175 if self.pos == 0 {
176 return None;
177 }
178 self.buf[..self.pos]
179 .grapheme_indices(true)
180 .rev()
181 .take(n)
182 .last()
183 .map(|(i, _)| i)
184 }
185
186 pub fn insert(&mut self, ch: char, n: RepeatCount) -> Option<bool> {
191 let shift = ch.len_utf8() * n;
192 if self.buf.len() + shift > self.buf.capacity() {
193 return None;
194 }
195 let push = self.pos == self.buf.len();
196 if n == 1 {
197 self.buf.insert(self.pos, ch);
198 for cl in &self.cl {
199 cl.borrow_mut().insert_char(self.pos, ch);
200 }
201 } else {
202 let text = iter::repeat(ch).take(n).collect::<String>();
203 let pos = self.pos;
204 self.insert_str(pos, &text);
205 }
206 self.pos += shift;
207 Some(push)
208 }
209
210 pub fn yank(&mut self, text: &str, n: RepeatCount) -> Option<bool> {
214 let shift = text.len() * n;
215 if text.is_empty() || (self.buf.len() + shift) > self.buf.capacity() {
216 return None;
217 }
218 let push = self.pos == self.buf.len();
219 let pos = self.pos;
220 if n == 1 {
221 self.insert_str(pos, text);
222 } else {
223 let text = iter::repeat(text).take(n).collect::<String>();
224 self.insert_str(pos, &text);
225 }
226 self.pos += shift;
227 Some(push)
228 }
229
230 pub fn yank_pop(&mut self, yank_size: usize, text: &str) -> Option<bool> {
232 let end = self.pos;
233 let start = end - yank_size;
234 self.drain(start..end, Direction::default());
235 self.pos -= yank_size;
236 self.yank(text, 1)
237 }
238
239 pub fn move_backward(&mut self, n: RepeatCount) -> bool {
241 match self.prev_pos(n) {
242 Some(pos) => {
243 self.pos = pos;
244 true
245 }
246 None => false,
247 }
248 }
249
250 pub fn move_forward(&mut self, n: RepeatCount) -> bool {
252 match self.next_pos(n) {
253 Some(pos) => {
254 self.pos = pos;
255 true
256 }
257 None => false,
258 }
259 }
260
261 pub fn move_home(&mut self) -> bool {
263 if self.pos > 0 {
264 self.pos = 0;
265 true
266 } else {
267 false
268 }
269 }
270
271 pub fn move_end(&mut self) -> bool {
273 if self.pos == self.buf.len() {
274 false
275 } else {
276 self.pos = self.buf.len();
277 true
278 }
279 }
280
281 pub fn delete(&mut self, n: RepeatCount) -> Option<String> {
286 match self.next_pos(n) {
287 Some(pos) => {
288 let start = self.pos;
289 let chars = self
290 .drain(start..pos, Direction::Forward)
291 .collect::<String>();
292 Some(chars)
293 }
294 None => None,
295 }
296 }
297
298 pub fn backspace(&mut self, n: RepeatCount) -> bool {
301 match self.prev_pos(n) {
302 Some(pos) => {
303 let end = self.pos;
304 self.drain(pos..end, Direction::Backward);
305 self.pos = pos;
306 true
307 }
308 None => false,
309 }
310 }
311
312 pub fn kill_line(&mut self) -> bool {
314 if !self.buf.is_empty() && self.pos < self.buf.len() {
315 let start = self.pos;
316 let end = self.buf.len();
317 self.drain(start..end, Direction::Forward);
318 true
319 } else {
320 false
321 }
322 }
323
324 pub fn discard_line(&mut self) -> bool {
326 if self.pos > 0 && !self.buf.is_empty() {
327 let end = self.pos;
328 self.drain(0..end, Direction::Backward);
329 self.pos = 0;
330 true
331 } else {
332 false
333 }
334 }
335
336 pub fn transpose_chars(&mut self) -> bool {
338 if self.pos == 0 || self.buf.graphemes(true).count() < 2 {
339 return false;
340 }
341 if self.pos == self.buf.len() {
342 self.move_backward(1);
343 }
344 let chars = self.delete(1).unwrap();
345 self.move_backward(1);
346 self.yank(&chars, 1);
347 self.move_forward(1);
348 true
349 }
350
351 fn prev_word_pos(&self, pos: usize, word_def: Word, n: RepeatCount) -> Option<usize> {
353 if pos == 0 {
354 return None;
355 }
356 let mut sow = 0;
357 let mut gis = self.buf[..pos].grapheme_indices(true).rev();
358 'outer: for _ in 0..n {
359 sow = 0;
360 let mut gj = gis.next();
361 'inner: loop {
362 match gj {
363 Some((j, y)) => {
364 let gi = gis.next();
365 match gi {
366 Some((_, x)) => {
367 if is_start_of_word(word_def, x, y) {
368 sow = j;
369 break 'inner;
370 }
371 gj = gi;
372 }
373 None => {
374 break 'outer;
375 }
376 }
377 }
378 None => {
379 break 'outer;
380 }
381 }
382 }
383 }
384 Some(sow)
385 }
386
387 pub fn move_to_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
389 if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
390 self.pos = pos;
391 true
392 } else {
393 false
394 }
395 }
396
397 pub fn delete_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
400 if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
401 let end = self.pos;
402 self.drain(pos..end, Direction::Backward);
403 self.pos = pos;
404 true
405 } else {
406 false
407 }
408 }
409
410 fn next_word_pos(&self, pos: usize, at: At, word_def: Word, n: RepeatCount) -> Option<usize> {
411 if pos == self.buf.len() {
412 return None;
413 }
414 let mut wp = 0;
415 let mut gis = self.buf[pos..].grapheme_indices(true);
416 let mut gi = if at == At::BeforeEnd {
417 gis.next()
419 } else {
420 None
421 };
422 'outer: for _ in 0..n {
423 wp = 0;
424 gi = gis.next();
425 'inner: loop {
426 match gi {
427 Some((i, x)) => {
428 let gj = gis.next();
429 match gj {
430 Some((j, y)) => {
431 if at == At::Start && is_start_of_word(word_def, x, y) {
432 wp = j;
433 break 'inner;
434 } else if at != At::Start && is_end_of_word(word_def, x, y) {
435 if word_def == Word::Emacs || at == At::AfterEnd {
436 wp = j;
437 } else {
438 wp = i;
439 }
440 break 'inner;
441 }
442 gi = gj;
443 }
444 None => {
445 break 'outer;
446 }
447 }
448 }
449 None => {
450 break 'outer;
451 }
452 }
453 }
454 }
455 if wp == 0 {
456 if word_def == Word::Emacs || at == At::AfterEnd {
457 Some(self.buf.len())
458 } else {
459 match gi {
460 Some((i, _)) if i != 0 => Some(i + pos),
461 _ => None,
462 }
463 }
464 } else {
465 Some(wp + pos)
466 }
467 }
468
469 pub fn move_to_next_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
471 if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
472 self.pos = pos;
473 true
474 } else {
475 false
476 }
477 }
478
479 fn search_char_pos(&self, cs: CharSearch, n: RepeatCount) -> Option<usize> {
480 let mut shift = 0;
481 let search_result = match cs {
482 CharSearch::Backward(c) | CharSearch::BackwardAfter(c) => self.buf[..self.pos]
483 .char_indices()
484 .rev()
485 .filter(|&(_, ch)| ch == c)
486 .take(n)
487 .last()
488 .map(|(i, _)| i),
489 CharSearch::Forward(c) | CharSearch::ForwardBefore(c) => {
490 if let Some(cc) = self.grapheme_at_cursor() {
491 shift = self.pos + cc.len();
492 if shift < self.buf.len() {
493 self.buf[shift..]
494 .char_indices()
495 .filter(|&(_, ch)| ch == c)
496 .take(n)
497 .last()
498 .map(|(i, _)| i)
499 } else {
500 None
501 }
502 } else {
503 None
504 }
505 }
506 };
507 if let Some(pos) = search_result {
508 Some(match cs {
509 CharSearch::Backward(_) => pos,
510 CharSearch::BackwardAfter(c) => pos + c.len_utf8(),
511 CharSearch::Forward(_) => shift + pos,
512 CharSearch::ForwardBefore(_) => {
513 shift + pos
514 - self.buf[..shift + pos]
515 .chars()
516 .next_back()
517 .unwrap()
518 .len_utf8()
519 }
520 })
521 } else {
522 None
523 }
524 }
525
526 pub fn move_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
529 if let Some(pos) = self.search_char_pos(cs, n) {
530 self.pos = pos;
531 true
532 } else {
533 false
534 }
535 }
536
537 pub fn delete_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
540 if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
541 let start = self.pos;
542 self.drain(start..pos, Direction::Forward);
543 true
544 } else {
545 false
546 }
547 }
548
549 pub fn delete_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
550 let search_result = match cs {
551 CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
552 _ => self.search_char_pos(cs, n),
553 };
554 if let Some(pos) = search_result {
555 match cs {
556 CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
557 let end = self.pos;
558 self.pos = pos;
559 self.drain(pos..end, Direction::Backward);
560 }
561 CharSearch::ForwardBefore(_) => {
562 let start = self.pos;
563 self.drain(start..pos, Direction::Forward);
564 }
565 CharSearch::Forward(c) => {
566 let start = self.pos;
567 self.drain(start..pos + c.len_utf8(), Direction::Forward);
568 }
569 };
570 true
571 } else {
572 false
573 }
574 }
575
576 fn skip_whitespace(&self) -> Option<usize> {
577 if self.pos == self.buf.len() {
578 return None;
579 }
580 self.buf[self.pos..]
581 .grapheme_indices(true)
582 .filter(|&(_, ch)| ch.chars().all(|c| c.is_alphanumeric()))
583 .map(|(i, _)| i)
584 .next()
585 .map(|i| i + self.pos)
586 }
587 pub fn edit_word(&mut self, a: WordAction) -> bool {
589 if let Some(start) = self.skip_whitespace() {
590 if let Some(end) = self.next_word_pos(start, At::AfterEnd, Word::Emacs, 1) {
591 if start == end {
592 return false;
593 }
594 let word = self
595 .drain(start..end, Direction::default())
596 .collect::<String>();
597 let result = match a {
598 WordAction::CAPITALIZE => {
599 let ch = (&word).graphemes(true).next().unwrap();
600 let cap = ch.to_uppercase();
601 cap + &word[ch.len()..].to_lowercase()
602 }
603 WordAction::LOWERCASE => word.to_lowercase(),
604 WordAction::UPPERCASE => word.to_uppercase(),
605 };
606 self.insert_str(start, &result);
607 self.pos = start + result.len();
608 return true;
609 }
610 }
611 false
612 }
613
614 pub fn transpose_words(&mut self, n: RepeatCount) -> bool {
616 let word_def = Word::Emacs;
617 self.move_to_next_word(At::AfterEnd, word_def, n);
618 let w2_end = self.pos;
619 self.move_to_prev_word(word_def, 1);
620 let w2_beg = self.pos;
621 self.move_to_prev_word(word_def, n);
622 let w1_beg = self.pos;
623 self.move_to_next_word(At::AfterEnd, word_def, 1);
624 let w1_end = self.pos;
625 if w1_beg == w2_beg || w2_beg < w1_end {
626 return false;
627 }
628
629 let w1 = self.buf[w1_beg..w1_end].to_owned();
630
631 let w2 = self
632 .drain(w2_beg..w2_end, Direction::default())
633 .collect::<String>();
634 self.insert_str(w2_beg, &w1);
635
636 self.drain(w1_beg..w1_end, Direction::default());
637 self.insert_str(w1_beg, &w2);
638
639 self.pos = w2_end;
640 true
641 }
642
643 pub fn replace(&mut self, range: Range<usize>, text: &str) {
646 let start = range.start;
647 for cl in &self.cl {
648 cl.borrow_mut()
649 .replace(start, self.buf.index(range.clone()), text);
650 }
651 self.buf.drain(range);
652 if start == self.buf.len() {
653 self.buf.push_str(text);
654 } else {
655 self.buf.insert_str(start, text);
656 }
657 self.pos = start + text.len();
658 }
659
660 pub fn insert_str(&mut self, idx: usize, s: &str) -> bool {
663 for cl in &self.cl {
664 cl.borrow_mut().insert_str(idx, s);
665 }
666 if idx == self.buf.len() {
667 self.buf.push_str(s);
668 true
669 } else {
670 self.buf.insert_str(idx, s);
671 false
672 }
673 }
674
675 pub fn delete_range(&mut self, range: Range<usize>) {
677 self.set_pos(range.start);
678 self.drain(range, Direction::default());
679 }
680
681 fn drain(&mut self, range: Range<usize>, dir: Direction) -> Drain {
682 for dl in &self.dl {
683 let mut lock = dl.try_lock();
684 if let Ok(mut dl) = lock {
685 dl.delete(range.start, &self.buf[range.start..range.end], dir);
686 }
687 }
688 for cl in &self.cl {
689 cl.borrow_mut()
690 .delete(range.start, &self.buf[range.start..range.end], dir);
691 }
692 self.buf.drain(range)
693 }
694
695 pub fn copy(&self, mvt: &Movement) -> Option<String> {
698 if self.is_empty() {
699 return None;
700 }
701 match *mvt {
702 Movement::WholeLine => Some(self.buf.clone()),
703 Movement::BeginningOfLine => if self.pos == 0 {
704 None
705 } else {
706 Some(self.buf[..self.pos].to_owned())
707 },
708 Movement::ViFirstPrint => if self.pos == 0 {
709 None
710 } else if let Some(pos) = self.next_word_pos(0, At::Start, Word::Big, 1) {
711 Some(self.buf[pos..self.pos].to_owned())
712 } else {
713 None
714 },
715 Movement::EndOfLine => if self.pos == self.buf.len() {
716 None
717 } else {
718 Some(self.buf[self.pos..].to_owned())
719 },
720 Movement::BackwardWord(n, word_def) => {
721 if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
722 Some(self.buf[pos..self.pos].to_owned())
723 } else {
724 None
725 }
726 }
727 Movement::ForwardWord(n, at, word_def) => {
728 if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
729 Some(self.buf[self.pos..pos].to_owned())
730 } else {
731 None
732 }
733 }
734 Movement::ViCharSearch(n, cs) => {
735 let search_result = match cs {
736 CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
737 _ => self.search_char_pos(cs, n),
738 };
739 if let Some(pos) = search_result {
740 Some(match cs {
741 CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
742 self.buf[pos..self.pos].to_owned()
743 }
744 CharSearch::ForwardBefore(_) => self.buf[self.pos..pos].to_owned(),
745 CharSearch::Forward(c) => self.buf[self.pos..pos + c.len_utf8()].to_owned(),
746 })
747 } else {
748 None
749 }
750 }
751 Movement::BackwardChar(n) => if let Some(pos) = self.prev_pos(n) {
752 Some(self.buf[pos..self.pos].to_owned())
753 } else {
754 None
755 },
756 Movement::ForwardChar(n) => if let Some(pos) = self.next_pos(n) {
757 Some(self.buf[self.pos..pos].to_owned())
758 } else {
759 None
760 },
761 }
762 }
763
764 pub fn kill(&mut self, mvt: &Movement) -> bool {
765 let notify = match *mvt {
766 Movement::ForwardChar(_) => false,
767 Movement::BackwardChar(_) => false,
768 _ => true,
769 };
770 if notify {
771 if let Some(dl) = self.dl.as_ref() {
772 let mut dl = dl.lock().unwrap();
773 dl.start_killing()
774 }
775 }
776 let killed = match *mvt {
777 Movement::ForwardChar(n) => {
778 self.delete(n).is_some()
780 }
781 Movement::BackwardChar(n) => {
782 self.backspace(n)
784 }
785 Movement::EndOfLine => {
786 self.kill_line()
788 }
789 Movement::WholeLine => {
790 self.move_home();
791 self.kill_line()
792 }
793 Movement::BeginningOfLine => {
794 self.discard_line()
796 }
797 Movement::BackwardWord(n, word_def) => {
798 self.delete_prev_word(word_def, n)
800 }
801 Movement::ForwardWord(n, at, word_def) => {
802 self.delete_word(at, word_def, n)
804 }
805 Movement::ViCharSearch(n, cs) => self.delete_to(cs, n),
806 Movement::ViFirstPrint => {
807 false }
809 };
810 if notify {
811 if let Some(dl) = self.dl.as_ref() {
812 let mut dl = dl.lock().unwrap();
813 dl.stop_killing()
814 }
815 }
816 killed
817 }
818}
819
820impl Deref for LineBuffer {
821 type Target = str;
822
823 fn deref(&self) -> &str {
824 self.as_str()
825 }
826}
827
828fn is_start_of_word(word_def: Word, previous: &str, grapheme: &str) -> bool {
829 (!is_word_char(word_def, previous) && is_word_char(word_def, grapheme))
830 || (word_def == Word::Vi && !is_other_char(previous) && is_other_char(grapheme))
831}
832fn is_end_of_word(word_def: Word, grapheme: &str, next: &str) -> bool {
833 (!is_word_char(word_def, next) && is_word_char(word_def, grapheme))
834 || (word_def == Word::Vi && !is_other_char(next) && is_other_char(grapheme))
835}
836
837fn is_word_char(word_def: Word, grapheme: &str) -> bool {
838 match word_def {
839 Word::Emacs => grapheme.chars().all(|c| c.is_alphanumeric()),
840 Word::Vi => is_vi_word_char(grapheme),
841 Word::Big => !grapheme.chars().any(|c| c.is_whitespace()),
842 }
843}
844fn is_vi_word_char(grapheme: &str) -> bool {
845 grapheme.chars().all(|c| c.is_alphanumeric()) || grapheme == "_"
846}
847fn is_other_char(grapheme: &str) -> bool {
848 !(grapheme.chars().any(|c| c.is_whitespace()) || is_vi_word_char(grapheme))
849}
850
851#[cfg(test)]
852mod test {
853 use super::{ChangeListener, DeleteListener, Direction, LineBuffer, WordAction, MAX_LINE};
854 use keymap::{At, CharSearch, Word};
855 use std::cell::RefCell;
856 use std::rc::Rc;
857
858 struct Listener {
859 deleted_str: Option<String>,
860 }
861
862 impl Listener {
863 fn new() -> Rc<RefCell<Listener>> {
864 let l = Listener { deleted_str: None };
865 Rc::new(RefCell::new(l))
866 }
867
868 fn assert_deleted_str_eq(&self, expected: &str) {
869 let actual = self.deleted_str.as_ref().expect("no deleted string");
870 assert_eq!(expected, actual)
871 }
872 }
873
874 impl DeleteListener for Listener {
875 fn start_killing(&mut self) {}
876 fn delete(&mut self, _: usize, string: &str, _: Direction) {
877 self.deleted_str = Some(string.to_owned());
878 }
879 fn stop_killing(&mut self) {}
880 }
881 impl ChangeListener for Listener {
882 fn insert_char(&mut self, _: usize, _: char) {}
883 fn insert_str(&mut self, _: usize, _: &str) {}
884 fn replace(&mut self, _: usize, _: &str, _: &str) {}
885 }
886
887 #[test]
888 fn next_pos() {
889 let s = LineBuffer::init("ö̲g̈", 0, None);
890 assert_eq!(7, s.len());
891 let pos = s.next_pos(1);
892 assert_eq!(Some(4), pos);
893
894 let s = LineBuffer::init("ö̲g̈", 4, None);
895 let pos = s.next_pos(1);
896 assert_eq!(Some(7), pos);
897 }
898
899 #[test]
900 fn prev_pos() {
901 let s = LineBuffer::init("ö̲g̈", 4, None);
902 assert_eq!(7, s.len());
903 let pos = s.prev_pos(1);
904 assert_eq!(Some(0), pos);
905
906 let s = LineBuffer::init("ö̲g̈", 7, None);
907 let pos = s.prev_pos(1);
908 assert_eq!(Some(4), pos);
909 }
910
911 #[test]
912 fn insert() {
913 let mut s = LineBuffer::with_capacity(MAX_LINE);
914 let push = s.insert('α', 1).unwrap();
915 assert_eq!("α", s.buf);
916 assert_eq!(2, s.pos);
917 assert_eq!(true, push);
918
919 let push = s.insert('ß', 1).unwrap();
920 assert_eq!("αß", s.buf);
921 assert_eq!(4, s.pos);
922 assert_eq!(true, push);
923
924 s.pos = 0;
925 let push = s.insert('γ', 1).unwrap();
926 assert_eq!("γαß", s.buf);
927 assert_eq!(2, s.pos);
928 assert_eq!(false, push);
929 }
930
931 #[test]
932 fn yank_after() {
933 let mut s = LineBuffer::init("αß", 2, None);
934 s.move_forward(1);
935 let ok = s.yank("γδε", 1);
936 assert_eq!(Some(true), ok);
937 assert_eq!("αßγδε", s.buf);
938 assert_eq!(10, s.pos);
939 }
940
941 #[test]
942 fn yank_before() {
943 let mut s = LineBuffer::init("αε", 2, None);
944 let ok = s.yank("ßγδ", 1);
945 assert_eq!(Some(false), ok);
946 assert_eq!("αßγδε", s.buf);
947 assert_eq!(8, s.pos);
948 }
949
950 #[test]
951 fn moves() {
952 let mut s = LineBuffer::init("αß", 4, None);
953 let ok = s.move_backward(1);
954 assert_eq!("αß", s.buf);
955 assert_eq!(2, s.pos);
956 assert_eq!(true, ok);
957
958 let ok = s.move_forward(1);
959 assert_eq!("αß", s.buf);
960 assert_eq!(4, s.pos);
961 assert_eq!(true, ok);
962
963 let ok = s.move_home();
964 assert_eq!("αß", s.buf);
965 assert_eq!(0, s.pos);
966 assert_eq!(true, ok);
967
968 let ok = s.move_end();
969 assert_eq!("αß", s.buf);
970 assert_eq!(4, s.pos);
971 assert_eq!(true, ok);
972 }
973
974 #[test]
975 fn move_grapheme() {
976 let mut s = LineBuffer::init("ag̈", 4, None);
977 assert_eq!(4, s.len());
978 let ok = s.move_backward(1);
979 assert_eq!(true, ok);
980 assert_eq!(1, s.pos);
981
982 let ok = s.move_forward(1);
983 assert_eq!(true, ok);
984 assert_eq!(4, s.pos);
985 }
986
987 #[test]
988 fn delete() {
989 let cl = Listener::new();
990 let mut s = LineBuffer::init("αß", 2, Some(cl.clone()));
991 let chars = s.delete(1);
992 assert_eq!("α", s.buf);
993 assert_eq!(2, s.pos);
994 assert_eq!(Some("ß".to_owned()), chars);
995
996 let ok = s.backspace(1);
997 assert_eq!("", s.buf);
998 assert_eq!(0, s.pos);
999 assert_eq!(true, ok);
1000 cl.borrow().assert_deleted_str_eq("α");
1001 }
1002
1003 #[test]
1004 fn kill() {
1005 let cl = Listener::new();
1006 let mut s = LineBuffer::init("αßγδε", 6, Some(cl.clone()));
1007 let ok = s.kill_line();
1008 assert_eq!("αßγ", s.buf);
1009 assert_eq!(6, s.pos);
1010 assert_eq!(true, ok);
1011 cl.borrow().assert_deleted_str_eq("δε");
1012
1013 s.pos = 4;
1014 let ok = s.discard_line();
1015 assert_eq!("γ", s.buf);
1016 assert_eq!(0, s.pos);
1017 assert_eq!(true, ok);
1018 cl.borrow().assert_deleted_str_eq("αß");
1019 }
1020
1021 #[test]
1022 fn transpose() {
1023 let mut s = LineBuffer::init("aßc", 1, None);
1024 let ok = s.transpose_chars();
1025 assert_eq!("ßac", s.buf);
1026 assert_eq!(3, s.pos);
1027 assert_eq!(true, ok);
1028
1029 s.buf = String::from("aßc");
1030 s.pos = 3;
1031 let ok = s.transpose_chars();
1032 assert_eq!("acß", s.buf);
1033 assert_eq!(4, s.pos);
1034 assert_eq!(true, ok);
1035
1036 s.buf = String::from("aßc");
1037 s.pos = 4;
1038 let ok = s.transpose_chars();
1039 assert_eq!("acß", s.buf);
1040 assert_eq!(4, s.pos);
1041 assert_eq!(true, ok);
1042 }
1043
1044 #[test]
1045 fn move_to_prev_word() {
1046 let mut s = LineBuffer::init("a ß c", 6, None); let ok = s.move_to_prev_word(Word::Emacs, 1);
1048 assert_eq!("a ß c", s.buf);
1049 assert_eq!(2, s.pos); assert!(true, ok);
1051
1052 assert!(s.move_end()); assert_eq!(7, s.pos);
1054 let ok = s.move_to_prev_word(Word::Emacs, 1);
1055 assert!(true, ok);
1056 assert_eq!(6, s.pos); let ok = s.move_to_prev_word(Word::Emacs, 2);
1059 assert!(true, ok);
1060 assert_eq!(0, s.pos);
1061 }
1062
1063 #[test]
1064 fn move_to_prev_vi_word() {
1065 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19, None);
1066 let ok = s.move_to_prev_word(Word::Vi, 1);
1067 assert!(ok);
1068 assert_eq!(17, s.pos);
1069 let ok = s.move_to_prev_word(Word::Vi, 1);
1070 assert!(ok);
1071 assert_eq!(15, s.pos);
1072 let ok = s.move_to_prev_word(Word::Vi, 1);
1073 assert!(ok);
1074 assert_eq!(12, s.pos);
1075 let ok = s.move_to_prev_word(Word::Vi, 1);
1076 assert!(ok);
1077 assert_eq!(11, s.pos);
1078 let ok = s.move_to_prev_word(Word::Vi, 1);
1079 assert!(ok);
1080 assert_eq!(7, s.pos);
1081 let ok = s.move_to_prev_word(Word::Vi, 1);
1082 assert!(ok);
1083 assert_eq!(6, s.pos);
1084 let ok = s.move_to_prev_word(Word::Vi, 1);
1085 assert!(ok);
1086 assert_eq!(0, s.pos);
1087 let ok = s.move_to_prev_word(Word::Vi, 1);
1088 assert!(!ok);
1089 }
1090
1091 #[test]
1092 fn move_to_prev_big_word() {
1093 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19, None);
1094 let ok = s.move_to_prev_word(Word::Big, 1);
1095 assert!(ok);
1096 assert_eq!(17, s.pos);
1097 let ok = s.move_to_prev_word(Word::Big, 1);
1098 assert!(ok);
1099 assert_eq!(6, s.pos);
1100 let ok = s.move_to_prev_word(Word::Big, 1);
1101 assert!(ok);
1102 assert_eq!(0, s.pos);
1103 let ok = s.move_to_prev_word(Word::Big, 1);
1104 assert!(!ok);
1105 }
1106
1107 #[test]
1108 fn move_to_forward() {
1109 let mut s = LineBuffer::init("αßγδε", 2, None);
1110 let ok = s.move_to(CharSearch::ForwardBefore('ε'), 1);
1111 assert_eq!(true, ok);
1112 assert_eq!(6, s.pos);
1113
1114 let mut s = LineBuffer::init("αßγδε", 2, None);
1115 let ok = s.move_to(CharSearch::Forward('ε'), 1);
1116 assert_eq!(true, ok);
1117 assert_eq!(8, s.pos);
1118
1119 let mut s = LineBuffer::init("αßγδε", 2, None);
1120 let ok = s.move_to(CharSearch::Forward('ε'), 10);
1121 assert_eq!(true, ok);
1122 assert_eq!(8, s.pos);
1123 }
1124
1125 #[test]
1126 fn move_to_backward() {
1127 let mut s = LineBuffer::init("αßγδε", 8, None);
1128 let ok = s.move_to(CharSearch::BackwardAfter('ß'), 1);
1129 assert_eq!(true, ok);
1130 assert_eq!(4, s.pos);
1131
1132 let mut s = LineBuffer::init("αßγδε", 8, None);
1133 let ok = s.move_to(CharSearch::Backward('ß'), 1);
1134 assert_eq!(true, ok);
1135 assert_eq!(2, s.pos);
1136 }
1137
1138 #[test]
1139 fn delete_prev_word() {
1140 let cl = Listener::new();
1141 let mut s = LineBuffer::init("a ß c", 6, Some(cl.clone()));
1142 let ok = s.delete_prev_word(Word::Big, 1);
1143 assert_eq!("a c", s.buf);
1144 assert_eq!(2, s.pos);
1145 assert_eq!(true, ok);
1146 cl.borrow().assert_deleted_str_eq("ß ");
1147 }
1148
1149 #[test]
1150 fn move_to_next_word() {
1151 let mut s = LineBuffer::init("a ß c", 1, None); let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1153 assert_eq!("a ß c", s.buf);
1154 assert_eq!(true, ok);
1155 assert_eq!(4, s.pos); let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1158 assert_eq!(true, ok);
1159 assert_eq!(7, s.pos); s.move_home();
1162 let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
1163 assert_eq!(true, ok);
1164 assert_eq!(1, s.pos); let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 2);
1167 assert_eq!(true, ok);
1168 assert_eq!(7, s.pos); }
1170
1171 #[test]
1172 fn move_to_end_of_word() {
1173 let mut s = LineBuffer::init("a ßeta c", 1, None);
1174 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1175 assert_eq!("a ßeta c", s.buf);
1176 assert_eq!(6, s.pos);
1177 assert_eq!(true, ok);
1178 }
1179
1180 #[test]
1181 fn move_to_end_of_vi_word() {
1182 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1183 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1184 assert!(ok);
1185 assert_eq!(4, s.pos);
1186 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1187 assert!(ok);
1188 assert_eq!(6, s.pos);
1189 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1190 assert!(ok);
1191 assert_eq!(10, s.pos);
1192 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1193 assert!(ok);
1194 assert_eq!(11, s.pos);
1195 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1196 assert!(ok);
1197 assert_eq!(14, s.pos);
1198 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1199 assert!(ok);
1200 assert_eq!(15, s.pos);
1201 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1202 assert!(ok);
1203 assert_eq!(18, s.pos);
1204 let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
1205 assert!(!ok);
1206 }
1207
1208 #[test]
1209 fn move_to_end_of_big_word() {
1210 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1211 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1212 assert!(ok);
1213 assert_eq!(4, s.pos);
1214 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1215 assert!(ok);
1216 assert_eq!(15, s.pos);
1217 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1218 assert!(ok);
1219 assert_eq!(18, s.pos);
1220 let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
1221 assert!(!ok);
1222 }
1223
1224 #[test]
1225 fn move_to_start_of_word() {
1226 let mut s = LineBuffer::init("a ß c", 2, None);
1227 let ok = s.move_to_next_word(At::Start, Word::Emacs, 1);
1228 assert_eq!("a ß c", s.buf);
1229 assert_eq!(6, s.pos);
1230 assert_eq!(true, ok);
1231 }
1232
1233 #[test]
1234 fn move_to_start_of_vi_word() {
1235 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1236 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1237 assert!(ok);
1238 assert_eq!(6, s.pos);
1239 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1240 assert!(ok);
1241 assert_eq!(7, s.pos);
1242 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1243 assert!(ok);
1244 assert_eq!(11, s.pos);
1245 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1246 assert!(ok);
1247 assert_eq!(12, s.pos);
1248 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1249 assert!(ok);
1250 assert_eq!(15, s.pos);
1251 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1252 assert!(ok);
1253 assert_eq!(17, s.pos);
1254 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1255 assert!(ok);
1256 assert_eq!(18, s.pos);
1257 let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
1258 assert!(!ok);
1259 }
1260
1261 #[test]
1262 fn move_to_start_of_big_word() {
1263 let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
1264 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1265 assert!(ok);
1266 assert_eq!(6, s.pos);
1267 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1268 assert!(ok);
1269 assert_eq!(17, s.pos);
1270 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1271 assert!(ok);
1272 assert_eq!(18, s.pos);
1273 let ok = s.move_to_next_word(At::Start, Word::Big, 1);
1274 assert!(!ok);
1275 }
1276
1277 #[test]
1278 fn delete_word() {
1279 let cl = Listener::new();
1280 let mut s = LineBuffer::init("a ß c", 1, Some(cl.clone()));
1281 let ok = s.delete_word(At::AfterEnd, Word::Emacs, 1);
1282 assert_eq!("a c", s.buf);
1283 assert_eq!(1, s.pos);
1284 assert_eq!(true, ok);
1285 cl.borrow().assert_deleted_str_eq(" ß");
1286
1287 let mut s = LineBuffer::init("test", 0, Some(cl.clone()));
1288 let ok = s.delete_word(At::AfterEnd, Word::Vi, 1);
1289 assert_eq!("", s.buf);
1290 assert_eq!(0, s.pos);
1291 assert_eq!(true, ok);
1292 cl.borrow().assert_deleted_str_eq("test");
1293 }
1294
1295 #[test]
1296 fn delete_til_start_of_word() {
1297 let cl = Listener::new();
1298 let mut s = LineBuffer::init("a ß c", 2, Some(cl.clone()));
1299 let ok = s.delete_word(At::Start, Word::Emacs, 1);
1300 assert_eq!("a c", s.buf);
1301 assert_eq!(2, s.pos);
1302 assert_eq!(true, ok);
1303 cl.borrow().assert_deleted_str_eq("ß ");
1304 }
1305
1306 #[test]
1307 fn delete_to_forward() {
1308 let cl = Listener::new();
1309 let mut s = LineBuffer::init("αßγδε", 2, Some(cl.clone()));
1310 let ok = s.delete_to(CharSearch::ForwardBefore('ε'), 1);
1311 assert_eq!(true, ok);
1312 cl.borrow().assert_deleted_str_eq("ßγδ");
1313 assert_eq!("αε", s.buf);
1314 assert_eq!(2, s.pos);
1315
1316 let mut s = LineBuffer::init("αßγδε", 2, Some(cl.clone()));
1317 let ok = s.delete_to(CharSearch::Forward('ε'), 1);
1318 assert_eq!(true, ok);
1319 cl.borrow().assert_deleted_str_eq("ßγδε");
1320 assert_eq!("α", s.buf);
1321 assert_eq!(2, s.pos);
1322 }
1323
1324 #[test]
1325 fn delete_to_backward() {
1326 let cl = Listener::new();
1327 let mut s = LineBuffer::init("αßγδε", 8, Some(cl.clone()));
1328 let ok = s.delete_to(CharSearch::BackwardAfter('α'), 1);
1329 assert_eq!(true, ok);
1330 cl.borrow().assert_deleted_str_eq("ßγδ");
1331 assert_eq!("αε", s.buf);
1332 assert_eq!(2, s.pos);
1333
1334 let mut s = LineBuffer::init("αßγδε", 8, Some(cl.clone()));
1335 let ok = s.delete_to(CharSearch::Backward('ß'), 1);
1336 assert_eq!(true, ok);
1337 cl.borrow().assert_deleted_str_eq("ßγδ");
1338 assert_eq!("αε", s.buf);
1339 assert_eq!(2, s.pos);
1340 }
1341
1342 #[test]
1343 fn edit_word() {
1344 let mut s = LineBuffer::init("a ßeta c", 1, None);
1345 assert!(s.edit_word(WordAction::UPPERCASE));
1346 assert_eq!("a SSETA c", s.buf);
1347 assert_eq!(7, s.pos);
1348
1349 let mut s = LineBuffer::init("a ßetA c", 1, None);
1350 assert!(s.edit_word(WordAction::LOWERCASE));
1351 assert_eq!("a ßeta c", s.buf);
1352 assert_eq!(7, s.pos);
1353
1354 let mut s = LineBuffer::init("a ßETA c", 1, None);
1355 assert!(s.edit_word(WordAction::CAPITALIZE));
1356 assert_eq!("a SSeta c", s.buf);
1357 assert_eq!(7, s.pos);
1358
1359 let mut s = LineBuffer::init("test", 1, None);
1360 assert!(s.edit_word(WordAction::CAPITALIZE));
1361 assert_eq!("tEst", s.buf);
1362 assert_eq!(4, s.pos);
1363 }
1364
1365 #[test]
1366 fn transpose_words() {
1367 let mut s = LineBuffer::init("ßeta / δelta__", 15, None);
1368 assert!(s.transpose_words(1));
1369 assert_eq!("δelta__ / ßeta", s.buf);
1370 assert_eq!(16, s.pos);
1371
1372 let mut s = LineBuffer::init("ßeta / δelta", 14, None);
1373 assert!(s.transpose_words(1));
1374 assert_eq!("δelta / ßeta", s.buf);
1375 assert_eq!(14, s.pos);
1376
1377 let mut s = LineBuffer::init(" / δelta", 8, None);
1378 assert!(!s.transpose_words(1));
1379
1380 let mut s = LineBuffer::init("ßeta / __", 9, None);
1381 assert!(!s.transpose_words(1));
1382 }
1383}