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