vi.c revision 1.8 1 /* $NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #if !defined(lint) && !defined(SCCSID)
41 #if 0
42 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
43 #else
44 __RCSID("$NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $");
45 #endif
46 #endif /* not lint && not SCCSID */
47
48 /*
49 * vi.c: Vi mode commands.
50 */
51 #include "sys.h"
52 #include "el.h"
53
54 private el_action_t cv_action(EditLine *, int);
55 private el_action_t cv_paste(EditLine *, int);
56
57 /* cv_action():
58 * Handle vi actions.
59 */
60 private el_action_t
61 cv_action(EditLine *el, int c)
62 {
63 char *cp, *kp;
64
65 if (el->el_chared.c_vcmd.action & DELETE) {
66 el->el_chared.c_vcmd.action = NOP;
67 el->el_chared.c_vcmd.pos = 0;
68
69 el->el_chared.c_undo.isize = 0;
70 el->el_chared.c_undo.dsize = 0;
71 kp = el->el_chared.c_undo.buf;
72 for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
73 *kp++ = *cp;
74 el->el_chared.c_undo.dsize++;
75 }
76
77 el->el_chared.c_undo.action = INSERT;
78 el->el_chared.c_undo.ptr = el->el_line.buffer;
79 el->el_line.lastchar = el->el_line.buffer;
80 el->el_line.cursor = el->el_line.buffer;
81 if (c & INSERT)
82 el->el_map.current = el->el_map.key;
83
84 return (CC_REFRESH);
85 }
86 el->el_chared.c_vcmd.pos = el->el_line.cursor;
87 el->el_chared.c_vcmd.action = c;
88 return (CC_ARGHACK);
89
90 #ifdef notdef
91 /*
92 * I don't think that this is needed. But we keep it for now
93 */
94 else
95 if (el_chared.c_vcmd.action == NOP) {
96 el->el_chared.c_vcmd.pos = el->el_line.cursor;
97 el->el_chared.c_vcmd.action = c;
98 return (CC_ARGHACK);
99 } else {
100 el->el_chared.c_vcmd.action = 0;
101 el->el_chared.c_vcmd.pos = 0;
102 return (CC_ERROR);
103 }
104 #endif
105 }
106
107
108 /* cv_paste():
109 * Paste previous deletion before or after the cursor
110 */
111 private el_action_t
112 cv_paste(EditLine *el, int c)
113 {
114 char *ptr;
115 c_undo_t *un = &el->el_chared.c_undo;
116
117 #ifdef DEBUG_PASTE
118 (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
119 un->action, un->buf, un->isize, un->dsize);
120 #endif
121 if (un->isize == 0)
122 return (CC_ERROR);
123
124 if (!c && el->el_line.cursor < el->el_line.lastchar)
125 el->el_line.cursor++;
126 ptr = el->el_line.cursor;
127
128 c_insert(el, (int) un->isize);
129 if (el->el_line.cursor + un->isize > el->el_line.lastchar)
130 return (CC_ERROR);
131 (void) memcpy(ptr, un->buf, un->isize);
132 return (CC_REFRESH);
133 }
134
135
136 /* vi_paste_next():
137 * Vi paste previous deletion to the right of the cursor
138 * [p]
139 */
140 protected el_action_t
141 /*ARGSUSED*/
142 vi_paste_next(EditLine *el, int c)
143 {
144
145 return (cv_paste(el, 0));
146 }
147
148
149 /* vi_paste_prev():
150 * Vi paste previous deletion to the left of the cursor
151 * [P]
152 */
153 protected el_action_t
154 /*ARGSUSED*/
155 vi_paste_prev(EditLine *el, int c)
156 {
157
158 return (cv_paste(el, 1));
159 }
160
161
162 /* vi_prev_space_word():
163 * Vi move to the previous space delimited word
164 * [B]
165 */
166 protected el_action_t
167 /*ARGSUSED*/
168 vi_prev_space_word(EditLine *el, int c)
169 {
170
171 if (el->el_line.cursor == el->el_line.buffer)
172 return (CC_ERROR);
173
174 el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
175 el->el_line.buffer,
176 el->el_state.argument,
177 cv__isword);
178
179 if (el->el_chared.c_vcmd.action & DELETE) {
180 cv_delfini(el);
181 return (CC_REFRESH);
182 }
183 return (CC_CURSOR);
184 }
185
186
187 /* vi_prev_word():
188 * Vi move to the previous word
189 * [B]
190 */
191 protected el_action_t
192 /*ARGSUSED*/
193 vi_prev_word(EditLine *el, int c)
194 {
195
196 if (el->el_line.cursor == el->el_line.buffer)
197 return (CC_ERROR);
198
199 el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
200 el->el_line.buffer,
201 el->el_state.argument,
202 ce__isword);
203
204 if (el->el_chared.c_vcmd.action & DELETE) {
205 cv_delfini(el);
206 return (CC_REFRESH);
207 }
208 return (CC_CURSOR);
209 }
210
211
212 /* vi_next_space_word():
213 * Vi move to the next space delimited word
214 * [W]
215 */
216 protected el_action_t
217 /*ARGSUSED*/
218 vi_next_space_word(EditLine *el, int c)
219 {
220
221 if (el->el_line.cursor == el->el_line.lastchar)
222 return (CC_ERROR);
223
224 el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
225 el->el_line.lastchar,
226 el->el_state.argument,
227 cv__isword);
228
229 if (el->el_map.type == MAP_VI)
230 if (el->el_chared.c_vcmd.action & DELETE) {
231 cv_delfini(el);
232 return (CC_REFRESH);
233 }
234 return (CC_CURSOR);
235 }
236
237
238 /* vi_next_word():
239 * Vi move to the next word
240 * [w]
241 */
242 protected el_action_t
243 /*ARGSUSED*/
244 vi_next_word(EditLine *el, int c)
245 {
246
247 if (el->el_line.cursor == el->el_line.lastchar)
248 return (CC_ERROR);
249
250 el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
251 el->el_line.lastchar,
252 el->el_state.argument,
253 ce__isword);
254
255 if (el->el_map.type == MAP_VI)
256 if (el->el_chared.c_vcmd.action & DELETE) {
257 cv_delfini(el);
258 return (CC_REFRESH);
259 }
260 return (CC_CURSOR);
261 }
262
263
264 /* vi_change_case():
265 * Vi change case of character under the cursor and advance one character
266 * [~]
267 */
268 protected el_action_t
269 vi_change_case(EditLine *el, int c)
270 {
271
272 if (el->el_line.cursor < el->el_line.lastchar) {
273 c = *el->el_line.cursor;
274 if (isupper(c))
275 *el->el_line.cursor++ = tolower(c);
276 else if (islower(c))
277 *el->el_line.cursor++ = toupper(c);
278 else
279 el->el_line.cursor++;
280 re_fastaddc(el);
281 return (CC_NORM);
282 }
283 return (CC_ERROR);
284 }
285
286
287 /* vi_change_meta():
288 * Vi change prefix command
289 * [c]
290 */
291 protected el_action_t
292 /*ARGSUSED*/
293 vi_change_meta(EditLine *el, int c)
294 {
295
296 /*
297 * Delete with insert == change: first we delete and then we leave in
298 * insert mode.
299 */
300 return (cv_action(el, DELETE | INSERT));
301 }
302
303
304 /* vi_insert_at_bol():
305 * Vi enter insert mode at the beginning of line
306 * [I]
307 */
308 protected el_action_t
309 /*ARGSUSED*/
310 vi_insert_at_bol(EditLine *el, int c)
311 {
312
313 el->el_line.cursor = el->el_line.buffer;
314 el->el_chared.c_vcmd.ins = el->el_line.cursor;
315
316 el->el_chared.c_undo.ptr = el->el_line.cursor;
317 el->el_chared.c_undo.action = DELETE;
318
319 el->el_map.current = el->el_map.key;
320 return (CC_CURSOR);
321 }
322
323
324 /* vi_replace_char():
325 * Vi replace character under the cursor with the next character typed
326 * [r]
327 */
328 protected el_action_t
329 /*ARGSUSED*/
330 vi_replace_char(EditLine *el, int c)
331 {
332
333 el->el_map.current = el->el_map.key;
334 el->el_state.inputmode = MODE_REPLACE_1;
335 el->el_chared.c_undo.action = CHANGE;
336 el->el_chared.c_undo.ptr = el->el_line.cursor;
337 el->el_chared.c_undo.isize = 0;
338 el->el_chared.c_undo.dsize = 0;
339 return (CC_NORM);
340 }
341
342
343 /* vi_replace_mode():
344 * Vi enter replace mode
345 * [R]
346 */
347 protected el_action_t
348 /*ARGSUSED*/
349 vi_replace_mode(EditLine *el, int c)
350 {
351
352 el->el_map.current = el->el_map.key;
353 el->el_state.inputmode = MODE_REPLACE;
354 el->el_chared.c_undo.action = CHANGE;
355 el->el_chared.c_undo.ptr = el->el_line.cursor;
356 el->el_chared.c_undo.isize = 0;
357 el->el_chared.c_undo.dsize = 0;
358 return (CC_NORM);
359 }
360
361
362 /* vi_substitute_char():
363 * Vi replace character under the cursor and enter insert mode
364 * [r]
365 */
366 protected el_action_t
367 /*ARGSUSED*/
368 vi_substitute_char(EditLine *el, int c)
369 {
370
371 c_delafter(el, el->el_state.argument);
372 el->el_map.current = el->el_map.key;
373 return (CC_REFRESH);
374 }
375
376
377 /* vi_substitute_line():
378 * Vi substitute entire line
379 * [S]
380 */
381 protected el_action_t
382 /*ARGSUSED*/
383 vi_substitute_line(EditLine *el, int c)
384 {
385
386 (void) em_kill_line(el, 0);
387 el->el_map.current = el->el_map.key;
388 return (CC_REFRESH);
389 }
390
391
392 /* vi_change_to_eol():
393 * Vi change to end of line
394 * [C]
395 */
396 protected el_action_t
397 /*ARGSUSED*/
398 vi_change_to_eol(EditLine *el, int c)
399 {
400
401 (void) ed_kill_line(el, 0);
402 el->el_map.current = el->el_map.key;
403 return (CC_REFRESH);
404 }
405
406
407 /* vi_insert():
408 * Vi enter insert mode
409 * [i]
410 */
411 protected el_action_t
412 /*ARGSUSED*/
413 vi_insert(EditLine *el, int c)
414 {
415
416 el->el_map.current = el->el_map.key;
417
418 el->el_chared.c_vcmd.ins = el->el_line.cursor;
419 el->el_chared.c_undo.ptr = el->el_line.cursor;
420 el->el_chared.c_undo.action = DELETE;
421
422 return (CC_NORM);
423 }
424
425
426 /* vi_add():
427 * Vi enter insert mode after the cursor
428 * [a]
429 */
430 protected el_action_t
431 /*ARGSUSED*/
432 vi_add(EditLine *el, int c)
433 {
434 int ret;
435
436 el->el_map.current = el->el_map.key;
437 if (el->el_line.cursor < el->el_line.lastchar) {
438 el->el_line.cursor++;
439 if (el->el_line.cursor > el->el_line.lastchar)
440 el->el_line.cursor = el->el_line.lastchar;
441 ret = CC_CURSOR;
442 } else
443 ret = CC_NORM;
444
445 el->el_chared.c_vcmd.ins = el->el_line.cursor;
446 el->el_chared.c_undo.ptr = el->el_line.cursor;
447 el->el_chared.c_undo.action = DELETE;
448
449 return (ret);
450 }
451
452
453 /* vi_add_at_eol():
454 * Vi enter insert mode at end of line
455 * [A]
456 */
457 protected el_action_t
458 /*ARGSUSED*/
459 vi_add_at_eol(EditLine *el, int c)
460 {
461
462 el->el_map.current = el->el_map.key;
463 el->el_line.cursor = el->el_line.lastchar;
464
465 /* Mark where insertion begins */
466 el->el_chared.c_vcmd.ins = el->el_line.lastchar;
467 el->el_chared.c_undo.ptr = el->el_line.lastchar;
468 el->el_chared.c_undo.action = DELETE;
469 return (CC_CURSOR);
470 }
471
472
473 /* vi_delete_meta():
474 * Vi delete prefix command
475 * [d]
476 */
477 protected el_action_t
478 /*ARGSUSED*/
479 vi_delete_meta(EditLine *el, int c)
480 {
481
482 return (cv_action(el, DELETE));
483 }
484
485
486 /* vi_end_word():
487 * Vi move to the end of the current space delimited word
488 * [E]
489 */
490 protected el_action_t
491 /*ARGSUSED*/
492 vi_end_word(EditLine *el, int c)
493 {
494
495 if (el->el_line.cursor == el->el_line.lastchar)
496 return (CC_ERROR);
497
498 el->el_line.cursor = cv__endword(el->el_line.cursor,
499 el->el_line.lastchar, el->el_state.argument);
500
501 if (el->el_chared.c_vcmd.action & DELETE) {
502 el->el_line.cursor++;
503 cv_delfini(el);
504 return (CC_REFRESH);
505 }
506 return (CC_CURSOR);
507 }
508
509
510 /* vi_to_end_word():
511 * Vi move to the end of the current word
512 * [e]
513 */
514 protected el_action_t
515 /*ARGSUSED*/
516 vi_to_end_word(EditLine *el, int c)
517 {
518
519 if (el->el_line.cursor == el->el_line.lastchar)
520 return (CC_ERROR);
521
522 el->el_line.cursor = cv__endword(el->el_line.cursor,
523 el->el_line.lastchar, el->el_state.argument);
524
525 if (el->el_chared.c_vcmd.action & DELETE) {
526 el->el_line.cursor++;
527 cv_delfini(el);
528 return (CC_REFRESH);
529 }
530 return (CC_CURSOR);
531 }
532
533
534 /* vi_undo():
535 * Vi undo last change
536 * [u]
537 */
538 protected el_action_t
539 /*ARGSUSED*/
540 vi_undo(EditLine *el, int c)
541 {
542 char *cp, *kp;
543 char temp;
544 int i, size;
545 c_undo_t *un = &el->el_chared.c_undo;
546
547 #ifdef DEBUG_UNDO
548 (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
549 un->action, un->buf, un->isize, un->dsize);
550 #endif
551 switch (un->action) {
552 case DELETE:
553 if (un->dsize == 0)
554 return (CC_NORM);
555
556 (void) memcpy(un->buf, un->ptr, un->dsize);
557 for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
558 *cp = cp[un->dsize];
559
560 el->el_line.lastchar -= un->dsize;
561 el->el_line.cursor = un->ptr;
562
563 un->action = INSERT;
564 un->isize = un->dsize;
565 un->dsize = 0;
566 break;
567
568 case DELETE | INSERT:
569 size = un->isize - un->dsize;
570 if (size > 0)
571 i = un->dsize;
572 else
573 i = un->isize;
574 cp = un->ptr;
575 kp = un->buf;
576 while (i-- > 0) {
577 temp = *kp;
578 *kp++ = *cp;
579 *cp++ = temp;
580 }
581 if (size > 0) {
582 el->el_line.cursor = cp;
583 c_insert(el, size);
584 while (size-- > 0 && cp < el->el_line.lastchar) {
585 temp = *kp;
586 *kp++ = *cp;
587 *cp++ = temp;
588 }
589 } else if (size < 0) {
590 size = -size;
591 for (; cp <= el->el_line.lastchar; cp++) {
592 *kp++ = *cp;
593 *cp = cp[size];
594 }
595 el->el_line.lastchar -= size;
596 }
597 el->el_line.cursor = un->ptr;
598 i = un->dsize;
599 un->dsize = un->isize;
600 un->isize = i;
601 break;
602
603 case INSERT:
604 if (un->isize == 0)
605 return (CC_NORM);
606
607 el->el_line.cursor = un->ptr;
608 c_insert(el, (int) un->isize);
609 (void) memcpy(un->ptr, un->buf, un->isize);
610 un->action = DELETE;
611 un->dsize = un->isize;
612 un->isize = 0;
613 break;
614
615 case CHANGE:
616 if (un->isize == 0)
617 return (CC_NORM);
618
619 el->el_line.cursor = un->ptr;
620 size = (int) (el->el_line.cursor - el->el_line.lastchar);
621 if (size < un->isize)
622 size = un->isize;
623 cp = un->ptr;
624 kp = un->buf;
625 for (i = 0; i < size; i++) {
626 temp = *kp;
627 *kp++ = *cp;
628 *cp++ = temp;
629 }
630 un->dsize = 0;
631 break;
632
633 default:
634 return (CC_ERROR);
635 }
636
637 return (CC_REFRESH);
638 }
639
640
641 /* vi_command_mode():
642 * Vi enter command mode (use alternative key bindings)
643 * [<ESC>]
644 */
645 protected el_action_t
646 /*ARGSUSED*/
647 vi_command_mode(EditLine *el, int c)
648 {
649 int size;
650
651 /* [Esc] cancels pending action */
652 el->el_chared.c_vcmd.ins = 0;
653 el->el_chared.c_vcmd.action = NOP;
654 el->el_chared.c_vcmd.pos = 0;
655
656 el->el_state.doingarg = 0;
657 size = el->el_chared.c_undo.ptr - el->el_line.cursor;
658 if (size < 0)
659 size = -size;
660 if (el->el_chared.c_undo.action == (INSERT | DELETE) ||
661 el->el_chared.c_undo.action == DELETE)
662 el->el_chared.c_undo.dsize = size;
663 else
664 el->el_chared.c_undo.isize = size;
665
666 el->el_state.inputmode = MODE_INSERT;
667 el->el_map.current = el->el_map.alt;
668 #ifdef VI_MOVE
669 if (el->el_line.cursor > el->el_line.buffer)
670 el->el_line.cursor--;
671 #endif
672 return (CC_CURSOR);
673 }
674
675
676 /* vi_zero():
677 * Vi move to the beginning of line
678 * [0]
679 */
680 protected el_action_t
681 vi_zero(EditLine *el, int c)
682 {
683
684 if (el->el_state.doingarg) {
685 if (el->el_state.argument > 1000000)
686 return (CC_ERROR);
687 el->el_state.argument =
688 (el->el_state.argument * 10) + (c - '0');
689 return (CC_ARGHACK);
690 } else {
691 el->el_line.cursor = el->el_line.buffer;
692 if (el->el_chared.c_vcmd.action & DELETE) {
693 cv_delfini(el);
694 return (CC_REFRESH);
695 }
696 return (CC_CURSOR);
697 }
698 }
699
700
701 /* vi_delete_prev_char():
702 * Vi move to previous character (backspace)
703 * [^H]
704 */
705 protected el_action_t
706 /*ARGSUSED*/
707 vi_delete_prev_char(EditLine *el, int c)
708 {
709
710 if (el->el_chared.c_vcmd.ins == 0)
711 return (CC_ERROR);
712
713 if (el->el_chared.c_vcmd.ins >
714 el->el_line.cursor - el->el_state.argument)
715 return (CC_ERROR);
716
717 c_delbefore(el, el->el_state.argument);
718 el->el_line.cursor -= el->el_state.argument;
719
720 return (CC_REFRESH);
721 }
722
723
724 /* vi_list_or_eof():
725 * Vi list choices for completion or indicate end of file if empty line
726 * [^D]
727 */
728 protected el_action_t
729 /*ARGSUSED*/
730 vi_list_or_eof(EditLine *el, int c)
731 {
732
733 #ifdef notyet
734 if (el->el_line.cursor == el->el_line.lastchar &&
735 el->el_line.cursor == el->el_line.buffer) {
736 #endif
737 term_overwrite(el, STReof, 4); /* then do a EOF */
738 term__flush();
739 return (CC_EOF);
740 #ifdef notyet
741 } else {
742 re_goto_bottom(el);
743 *el->el_line.lastchar = '\0'; /* just in case */
744 return (CC_LIST_CHOICES);
745 }
746 #endif
747 }
748
749
750 /* vi_kill_line_prev():
751 * Vi cut from beginning of line to cursor
752 * [^U]
753 */
754 protected el_action_t
755 /*ARGSUSED*/
756 vi_kill_line_prev(EditLine *el, int c)
757 {
758 char *kp, *cp;
759
760 cp = el->el_line.buffer;
761 kp = el->el_chared.c_kill.buf;
762 while (cp < el->el_line.cursor)
763 *kp++ = *cp++; /* copy it */
764 el->el_chared.c_kill.last = kp;
765 c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
766 el->el_line.cursor = el->el_line.buffer; /* zap! */
767 return (CC_REFRESH);
768 }
769
770
771 /* vi_search_prev():
772 * Vi search history previous
773 * [?]
774 */
775 protected el_action_t
776 /*ARGSUSED*/
777 vi_search_prev(EditLine *el, int c)
778 {
779
780 return (cv_search(el, ED_SEARCH_PREV_HISTORY));
781 }
782
783
784 /* vi_search_next():
785 * Vi search history next
786 * [/]
787 */
788 protected el_action_t
789 /*ARGSUSED*/
790 vi_search_next(EditLine *el, int c)
791 {
792
793 return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
794 }
795
796
797 /* vi_repeat_search_next():
798 * Vi repeat current search in the same search direction
799 * [n]
800 */
801 protected el_action_t
802 /*ARGSUSED*/
803 vi_repeat_search_next(EditLine *el, int c)
804 {
805
806 if (el->el_search.patlen == 0)
807 return (CC_ERROR);
808 else
809 return (cv_repeat_srch(el, el->el_search.patdir));
810 }
811
812
813 /* vi_repeat_search_prev():
814 * Vi repeat current search in the opposite search direction
815 * [N]
816 */
817 /*ARGSUSED*/
818 protected el_action_t
819 vi_repeat_search_prev(EditLine *el, int c)
820 {
821
822 if (el->el_search.patlen == 0)
823 return (CC_ERROR);
824 else
825 return (cv_repeat_srch(el,
826 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
827 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
828 }
829
830
831 /* vi_next_char():
832 * Vi move to the character specified next
833 * [f]
834 */
835 protected el_action_t
836 /*ARGSUSED*/
837 vi_next_char(EditLine *el, int c)
838 {
839 char ch;
840
841 if (el_getc(el, &ch) != 1)
842 return (ed_end_of_file(el, 0));
843
844 el->el_search.chadir = CHAR_FWD;
845 el->el_search.chacha = ch;
846
847 return (cv_csearch_fwd(el, ch, el->el_state.argument, 0));
848
849 }
850
851
852 /* vi_prev_char():
853 * Vi move to the character specified previous
854 * [F]
855 */
856 protected el_action_t
857 /*ARGSUSED*/
858 vi_prev_char(EditLine *el, int c)
859 {
860 char ch;
861
862 if (el_getc(el, &ch) != 1)
863 return (ed_end_of_file(el, 0));
864
865 el->el_search.chadir = CHAR_BACK;
866 el->el_search.chacha = ch;
867
868 return (cv_csearch_back(el, ch, el->el_state.argument, 0));
869 }
870
871
872 /* vi_to_next_char():
873 * Vi move up to the character specified next
874 * [t]
875 */
876 protected el_action_t
877 /*ARGSUSED*/
878 vi_to_next_char(EditLine *el, int c)
879 {
880 char ch;
881
882 if (el_getc(el, &ch) != 1)
883 return (ed_end_of_file(el, 0));
884
885 return (cv_csearch_fwd(el, ch, el->el_state.argument, 1));
886
887 }
888
889
890 /* vi_to_prev_char():
891 * Vi move up to the character specified previous
892 * [T]
893 */
894 protected el_action_t
895 /*ARGSUSED*/
896 vi_to_prev_char(EditLine *el, int c)
897 {
898 char ch;
899
900 if (el_getc(el, &ch) != 1)
901 return (ed_end_of_file(el, 0));
902
903 return (cv_csearch_back(el, ch, el->el_state.argument, 1));
904 }
905
906
907 /* vi_repeat_next_char():
908 * Vi repeat current character search in the same search direction
909 * [;]
910 */
911 protected el_action_t
912 /*ARGSUSED*/
913 vi_repeat_next_char(EditLine *el, int c)
914 {
915
916 if (el->el_search.chacha == 0)
917 return (CC_ERROR);
918
919 return (el->el_search.chadir == CHAR_FWD
920 ? cv_csearch_fwd(el, el->el_search.chacha,
921 el->el_state.argument, 0)
922 : cv_csearch_back(el, el->el_search.chacha,
923 el->el_state.argument, 0));
924 }
925
926
927 /* vi_repeat_prev_char():
928 * Vi repeat current character search in the opposite search direction
929 * [,]
930 */
931 protected el_action_t
932 /*ARGSUSED*/
933 vi_repeat_prev_char(EditLine *el, int c)
934 {
935
936 if (el->el_search.chacha == 0)
937 return (CC_ERROR);
938
939 return el->el_search.chadir == CHAR_BACK ?
940 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
941 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
942 }
943