1 /* $NetBSD: vi.c,v 1.45 2014/06/18 18:12:28 christos Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #if !defined(lint) && !defined(SCCSID)
43 static char sccsid
[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
45 __RCSID("$NetBSD: vi.c,v 1.45 2014/06/18 18:12:28 christos Exp $");
47 #endif /* not lint && not SCCSID */
50 * vi.c: Vi mode commands.
54 private el_action_t
cv_action(EditLine
*, Int
);
55 private el_action_t
cv_paste(EditLine
*, Int
);
61 cv_action(EditLine
*el
, Int c
)
64 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
65 /* 'cc', 'dd' and (possibly) friends */
66 if (c
!= (Int
)el
->el_chared
.c_vcmd
.action
)
71 cv_yank(el
, el
->el_line
.buffer
,
72 (int)(el
->el_line
.lastchar
- el
->el_line
.buffer
));
73 el
->el_chared
.c_vcmd
.action
= NOP
;
74 el
->el_chared
.c_vcmd
.pos
= 0;
76 el
->el_line
.lastchar
= el
->el_line
.buffer
;
77 el
->el_line
.cursor
= el
->el_line
.buffer
;
80 el
->el_map
.current
= el
->el_map
.key
;
84 el
->el_chared
.c_vcmd
.pos
= el
->el_line
.cursor
;
85 el
->el_chared
.c_vcmd
.action
= c
;
90 * Paste previous deletion before or after the cursor
93 cv_paste(EditLine
*el
, Int c
)
95 c_kill_t
*k
= &el
->el_chared
.c_kill
;
96 size_t len
= (size_t)(k
->last
- k
->buf
);
98 if (k
->buf
== NULL
|| len
== 0)
101 (void) fprintf(el
->el_errfile
, "Paste: \"%.*s\"\n", (int)len
, k
->buf
);
106 if (!c
&& el
->el_line
.cursor
< el
->el_line
.lastchar
)
107 el
->el_line
.cursor
++;
109 c_insert(el
, (int)len
);
110 if (el
->el_line
.cursor
+ len
> el
->el_line
.lastchar
)
112 (void) memcpy(el
->el_line
.cursor
, k
->buf
, len
*
113 sizeof(*el
->el_line
.cursor
));
120 * Vi paste previous deletion to the right of the cursor
123 protected el_action_t
125 vi_paste_next(EditLine
*el
, Int c
__attribute__((__unused__
)))
128 return cv_paste(el
, 0);
133 * Vi paste previous deletion to the left of the cursor
136 protected el_action_t
138 vi_paste_prev(EditLine
*el
, Int c
__attribute__((__unused__
)))
141 return cv_paste(el
, 1);
145 /* vi_prev_big_word():
146 * Vi move to the previous space delimited word
149 protected el_action_t
151 vi_prev_big_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
154 if (el
->el_line
.cursor
== el
->el_line
.buffer
)
157 el
->el_line
.cursor
= cv_prev_word(el
->el_line
.cursor
,
159 el
->el_state
.argument
,
162 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
171 * Vi move to the previous word
174 protected el_action_t
176 vi_prev_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
179 if (el
->el_line
.cursor
== el
->el_line
.buffer
)
182 el
->el_line
.cursor
= cv_prev_word(el
->el_line
.cursor
,
184 el
->el_state
.argument
,
187 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
195 /* vi_next_big_word():
196 * Vi move to the next space delimited word
199 protected el_action_t
201 vi_next_big_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
204 if (el
->el_line
.cursor
>= el
->el_line
.lastchar
- 1)
207 el
->el_line
.cursor
= cv_next_word(el
, el
->el_line
.cursor
,
208 el
->el_line
.lastchar
, el
->el_state
.argument
, cv__isWord
);
210 if (el
->el_map
.type
== MAP_VI
)
211 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
220 * Vi move to the next word
223 protected el_action_t
225 vi_next_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
228 if (el
->el_line
.cursor
>= el
->el_line
.lastchar
- 1)
231 el
->el_line
.cursor
= cv_next_word(el
, el
->el_line
.cursor
,
232 el
->el_line
.lastchar
, el
->el_state
.argument
, cv__isword
);
234 if (el
->el_map
.type
== MAP_VI
)
235 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
244 * Vi change case of character under the cursor and advance one character
247 protected el_action_t
248 vi_change_case(EditLine
*el
, Int c
)
252 if (el
->el_line
.cursor
>= el
->el_line
.lastchar
)
255 for (i
= 0; i
< el
->el_state
.argument
; i
++) {
257 c
= *el
->el_line
.cursor
;
259 *el
->el_line
.cursor
= Tolower(c
);
261 *el
->el_line
.cursor
= Toupper(c
);
263 if (++el
->el_line
.cursor
>= el
->el_line
.lastchar
) {
264 el
->el_line
.cursor
--;
275 * Vi change prefix command
278 protected el_action_t
280 vi_change_meta(EditLine
*el
, Int c
__attribute__((__unused__
)))
284 * Delete with insert == change: first we delete and then we leave in
287 return cv_action(el
, DELETE
| INSERT
);
291 /* vi_insert_at_bol():
292 * Vi enter insert mode at the beginning of line
295 protected el_action_t
297 vi_insert_at_bol(EditLine
*el
, Int c
__attribute__((__unused__
)))
300 el
->el_line
.cursor
= el
->el_line
.buffer
;
302 el
->el_map
.current
= el
->el_map
.key
;
307 /* vi_replace_char():
308 * Vi replace character under the cursor with the next character typed
311 protected el_action_t
313 vi_replace_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
316 if (el
->el_line
.cursor
>= el
->el_line
.lastchar
)
319 el
->el_map
.current
= el
->el_map
.key
;
320 el
->el_state
.inputmode
= MODE_REPLACE_1
;
326 /* vi_replace_mode():
327 * Vi enter replace mode
330 protected el_action_t
332 vi_replace_mode(EditLine
*el
, Int c
__attribute__((__unused__
)))
335 el
->el_map
.current
= el
->el_map
.key
;
336 el
->el_state
.inputmode
= MODE_REPLACE
;
342 /* vi_substitute_char():
343 * Vi replace character under the cursor and enter insert mode
346 protected el_action_t
348 vi_substitute_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
351 c_delafter(el
, el
->el_state
.argument
);
352 el
->el_map
.current
= el
->el_map
.key
;
357 /* vi_substitute_line():
358 * Vi substitute entire line
361 protected el_action_t
363 vi_substitute_line(EditLine
*el
, Int c
__attribute__((__unused__
)))
367 cv_yank(el
, el
->el_line
.buffer
,
368 (int)(el
->el_line
.lastchar
- el
->el_line
.buffer
));
369 (void) em_kill_line(el
, 0);
370 el
->el_map
.current
= el
->el_map
.key
;
375 /* vi_change_to_eol():
376 * Vi change to end of line
379 protected el_action_t
381 vi_change_to_eol(EditLine
*el
, Int c
__attribute__((__unused__
)))
385 cv_yank(el
, el
->el_line
.cursor
,
386 (int)(el
->el_line
.lastchar
- el
->el_line
.cursor
));
387 (void) ed_kill_line(el
, 0);
388 el
->el_map
.current
= el
->el_map
.key
;
394 * Vi enter insert mode
397 protected el_action_t
399 vi_insert(EditLine
*el
, Int c
__attribute__((__unused__
)))
402 el
->el_map
.current
= el
->el_map
.key
;
409 * Vi enter insert mode after the cursor
412 protected el_action_t
414 vi_add(EditLine
*el
, Int c
__attribute__((__unused__
)))
418 el
->el_map
.current
= el
->el_map
.key
;
419 if (el
->el_line
.cursor
< el
->el_line
.lastchar
) {
420 el
->el_line
.cursor
++;
421 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
422 el
->el_line
.cursor
= el
->el_line
.lastchar
;
429 return (el_action_t
)ret
;
434 * Vi enter insert mode at end of line
437 protected el_action_t
439 vi_add_at_eol(EditLine
*el
, Int c
__attribute__((__unused__
)))
442 el
->el_map
.current
= el
->el_map
.key
;
443 el
->el_line
.cursor
= el
->el_line
.lastchar
;
450 * Vi delete prefix command
453 protected el_action_t
455 vi_delete_meta(EditLine
*el
, Int c
__attribute__((__unused__
)))
458 return cv_action(el
, DELETE
);
462 /* vi_end_big_word():
463 * Vi move to the end of the current space delimited word
466 protected el_action_t
468 vi_end_big_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
471 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
474 el
->el_line
.cursor
= cv__endword(el
->el_line
.cursor
,
475 el
->el_line
.lastchar
, el
->el_state
.argument
, cv__isWord
);
477 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
478 el
->el_line
.cursor
++;
487 * Vi move to the end of the current word
490 protected el_action_t
492 vi_end_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
495 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
498 el
->el_line
.cursor
= cv__endword(el
->el_line
.cursor
,
499 el
->el_line
.lastchar
, el
->el_state
.argument
, cv__isword
);
501 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
502 el
->el_line
.cursor
++;
511 * Vi undo last change
514 protected el_action_t
516 vi_undo(EditLine
*el
, Int c
__attribute__((__unused__
)))
518 c_undo_t un
= el
->el_chared
.c_undo
;
523 /* switch line buffer and undo buffer */
524 el
->el_chared
.c_undo
.buf
= el
->el_line
.buffer
;
525 el
->el_chared
.c_undo
.len
= el
->el_line
.lastchar
- el
->el_line
.buffer
;
526 el
->el_chared
.c_undo
.cursor
=
527 (int)(el
->el_line
.cursor
- el
->el_line
.buffer
);
528 el
->el_line
.limit
= un
.buf
+ (el
->el_line
.limit
- el
->el_line
.buffer
);
529 el
->el_line
.buffer
= un
.buf
;
530 el
->el_line
.cursor
= un
.buf
+ un
.cursor
;
531 el
->el_line
.lastchar
= un
.buf
+ un
.len
;
537 /* vi_command_mode():
538 * Vi enter command mode (use alternative key bindings)
541 protected el_action_t
543 vi_command_mode(EditLine
*el
, Int c
__attribute__((__unused__
)))
546 /* [Esc] cancels pending action */
547 el
->el_chared
.c_vcmd
.action
= NOP
;
548 el
->el_chared
.c_vcmd
.pos
= 0;
550 el
->el_state
.doingarg
= 0;
552 el
->el_state
.inputmode
= MODE_INSERT
;
553 el
->el_map
.current
= el
->el_map
.alt
;
555 if (el
->el_line
.cursor
> el
->el_line
.buffer
)
556 el
->el_line
.cursor
--;
563 * Vi move to the beginning of line
566 protected el_action_t
567 vi_zero(EditLine
*el
, Int c
)
570 if (el
->el_state
.doingarg
)
571 return ed_argument_digit(el
, c
);
573 el
->el_line
.cursor
= el
->el_line
.buffer
;
574 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
582 /* vi_delete_prev_char():
583 * Vi move to previous character (backspace)
584 * [^H] in insert mode only
586 protected el_action_t
588 vi_delete_prev_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
591 if (el
->el_line
.cursor
<= el
->el_line
.buffer
)
595 el
->el_line
.cursor
--;
601 * Vi list choices for completion or indicate end of file if empty line
604 protected el_action_t
606 vi_list_or_eof(EditLine
*el
, Int c
)
609 if (el
->el_line
.cursor
== el
->el_line
.lastchar
) {
610 if (el
->el_line
.cursor
== el
->el_line
.buffer
) {
611 terminal_writec(el
, c
); /* then do a EOF */
615 * Here we could list completions, but it is an
624 *el
->el_line
.lastchar
= '\0'; /* just in case */
625 return CC_LIST_CHOICES
;
628 * Just complain for now.
637 /* vi_kill_line_prev():
638 * Vi cut from beginning of line to cursor
641 protected el_action_t
643 vi_kill_line_prev(EditLine
*el
, Int c
__attribute__((__unused__
)))
647 cp
= el
->el_line
.buffer
;
648 kp
= el
->el_chared
.c_kill
.buf
;
649 while (cp
< el
->el_line
.cursor
)
650 *kp
++ = *cp
++; /* copy it */
651 el
->el_chared
.c_kill
.last
= kp
;
652 c_delbefore(el
, (int)(el
->el_line
.cursor
- el
->el_line
.buffer
));
653 el
->el_line
.cursor
= el
->el_line
.buffer
; /* zap! */
659 * Vi search history previous
662 protected el_action_t
664 vi_search_prev(EditLine
*el
, Int c
__attribute__((__unused__
)))
667 return cv_search(el
, ED_SEARCH_PREV_HISTORY
);
672 * Vi search history next
675 protected el_action_t
677 vi_search_next(EditLine
*el
, Int c
__attribute__((__unused__
)))
680 return cv_search(el
, ED_SEARCH_NEXT_HISTORY
);
684 /* vi_repeat_search_next():
685 * Vi repeat current search in the same search direction
688 protected el_action_t
690 vi_repeat_search_next(EditLine
*el
, Int c
__attribute__((__unused__
)))
693 if (el
->el_search
.patlen
== 0)
696 return cv_repeat_srch(el
, el
->el_search
.patdir
);
700 /* vi_repeat_search_prev():
701 * Vi repeat current search in the opposite search direction
705 protected el_action_t
706 vi_repeat_search_prev(EditLine
*el
, Int c
__attribute__((__unused__
)))
709 if (el
->el_search
.patlen
== 0)
712 return (cv_repeat_srch(el
,
713 el
->el_search
.patdir
== ED_SEARCH_PREV_HISTORY
?
714 ED_SEARCH_NEXT_HISTORY
: ED_SEARCH_PREV_HISTORY
));
719 * Vi move to the character specified next
722 protected el_action_t
724 vi_next_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
726 return cv_csearch(el
, CHAR_FWD
, -1, el
->el_state
.argument
, 0);
731 * Vi move to the character specified previous
734 protected el_action_t
736 vi_prev_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
738 return cv_csearch(el
, CHAR_BACK
, -1, el
->el_state
.argument
, 0);
742 /* vi_to_next_char():
743 * Vi move up to the character specified next
746 protected el_action_t
748 vi_to_next_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
750 return cv_csearch(el
, CHAR_FWD
, -1, el
->el_state
.argument
, 1);
754 /* vi_to_prev_char():
755 * Vi move up to the character specified previous
758 protected el_action_t
760 vi_to_prev_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
762 return cv_csearch(el
, CHAR_BACK
, -1, el
->el_state
.argument
, 1);
766 /* vi_repeat_next_char():
767 * Vi repeat current character search in the same search direction
770 protected el_action_t
772 vi_repeat_next_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
775 return cv_csearch(el
, el
->el_search
.chadir
, el
->el_search
.chacha
,
776 el
->el_state
.argument
, el
->el_search
.chatflg
);
780 /* vi_repeat_prev_char():
781 * Vi repeat current character search in the opposite search direction
784 protected el_action_t
786 vi_repeat_prev_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
789 int dir
= el
->el_search
.chadir
;
791 r
= cv_csearch(el
, -dir
, el
->el_search
.chacha
,
792 el
->el_state
.argument
, el
->el_search
.chatflg
);
793 el
->el_search
.chadir
= dir
;
799 * Vi go to matching () {} or []
802 protected el_action_t
804 vi_match(EditLine
*el
, Int c
__attribute__((__unused__
)))
806 const Char match_chars
[] = STR("()[]{}");
808 size_t delta
, i
, count
;
811 *el
->el_line
.lastchar
= '\0'; /* just in case */
813 i
= Strcspn(el
->el_line
.cursor
, match_chars
);
814 o_ch
= el
->el_line
.cursor
[i
];
817 delta
= (size_t)(Strchr(match_chars
, o_ch
) - match_chars
);
818 c_ch
= match_chars
[delta
^ 1];
820 delta
= 1 - (delta
& 1) * 2;
822 for (cp
= &el
->el_line
.cursor
[i
]; count
; ) {
824 if (cp
< el
->el_line
.buffer
|| cp
>= el
->el_line
.lastchar
)
828 else if (*cp
== c_ch
)
832 el
->el_line
.cursor
= cp
;
834 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
835 /* NB posix says char under cursor should NOT be deleted
836 for -ve delta - this is different to netbsd vi. */
838 el
->el_line
.cursor
++;
846 * Vi undo all changes to line
849 protected el_action_t
851 vi_undo_line(EditLine
*el
, Int c
__attribute__((__unused__
)))
859 * Vi go to specified column
861 * NB netbsd vi goes to screen column 'n', posix says nth character
863 protected el_action_t
865 vi_to_column(EditLine
*el
, Int c
__attribute__((__unused__
)))
868 el
->el_line
.cursor
= el
->el_line
.buffer
;
869 el
->el_state
.argument
--;
870 return ed_next_char(el
, 0);
874 * Vi yank to end of line
877 protected el_action_t
879 vi_yank_end(EditLine
*el
, Int c
__attribute__((__unused__
)))
882 cv_yank(el
, el
->el_line
.cursor
,
883 (int)(el
->el_line
.lastchar
- el
->el_line
.cursor
));
891 protected el_action_t
893 vi_yank(EditLine
*el
, Int c
__attribute__((__unused__
)))
896 return cv_action(el
, YANK
);
900 * Vi comment out current command
903 protected el_action_t
905 vi_comment_out(EditLine
*el
, Int c
__attribute__((__unused__
)))
908 el
->el_line
.cursor
= el
->el_line
.buffer
;
910 *el
->el_line
.cursor
= '#';
912 return ed_newline(el
, 0);
916 * Vi include shell alias
918 * NB: posix implies that we should enter insert mode, however
919 * this is against historical precedent...
921 protected el_action_t
923 vi_alias(EditLine
*el
, Int c
__attribute__((__unused__
)))
926 const char *alias_text
;
928 if (el
->el_chared
.c_aliasfun
== NULL
)
933 if (el_getc(el
, &alias_name
[1]) != 1)
936 alias_text
= (*el
->el_chared
.c_aliasfun
)(el
->el_chared
.c_aliasarg
,
938 if (alias_text
!= NULL
)
939 FUN(el
,push
)(el
, ct_decode_string(alias_text
, &el
->el_scratch
));
943 /* vi_to_history_line():
944 * Vi go to specified history file line.
947 protected el_action_t
949 vi_to_history_line(EditLine
*el
, Int c
__attribute__((__unused__
)))
951 int sv_event_no
= el
->el_history
.eventno
;
955 if (el
->el_history
.eventno
== 0) {
956 (void) Strncpy(el
->el_history
.buf
, el
->el_line
.buffer
,
958 el
->el_history
.last
= el
->el_history
.buf
+
959 (el
->el_line
.lastchar
- el
->el_line
.buffer
);
962 /* Lack of a 'count' means oldest, not 1 */
963 if (!el
->el_state
.doingarg
) {
964 el
->el_history
.eventno
= 0x7fffffff;
967 /* This is brain dead, all the rest of this code counts
968 * upwards going into the past. Here we need count in the
969 * other direction (to match the output of fc -l).
970 * I could change the world, but this seems to suffice.
972 el
->el_history
.eventno
= 1;
973 if (hist_get(el
) == CC_ERROR
)
975 el
->el_history
.eventno
= 1 + el
->el_history
.ev
.num
976 - el
->el_state
.argument
;
977 if (el
->el_history
.eventno
< 0) {
978 el
->el_history
.eventno
= sv_event_no
;
983 if (rval
== CC_ERROR
)
984 el
->el_history
.eventno
= sv_event_no
;
989 * Vi edit history line with vi
992 protected el_action_t
994 vi_histedit(EditLine
*el
, Int c
__attribute__((__unused__
)))
1000 char tempfile
[] = "/tmp/histedit.XXXXXXXXXX";
1005 if (el
->el_state
.doingarg
) {
1006 if (vi_to_history_line(el
, 0) == CC_ERROR
)
1010 fd
= mkstemp(tempfile
);
1013 len
= (size_t)(el
->el_line
.lastchar
- el
->el_line
.buffer
);
1014 #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
1015 cp
= el_malloc(TMP_BUFSIZ
* sizeof(*cp
));
1018 line
= el_malloc(len
* sizeof(*line
) + 1);
1021 Strncpy(line
, el
->el_line
.buffer
, len
);
1023 ct_wcstombs(cp
, line
, TMP_BUFSIZ
- 1);
1024 cp
[TMP_BUFSIZ
- 1] = '\0';
1027 write(fd
, "\n", (size_t)1);
1034 execlp("vi", "vi", tempfile
, (char *)NULL
);
1038 while (waitpid(pid
, &status
, 0) != pid
)
1040 lseek(fd
, (off_t
)0, SEEK_SET
);
1041 st
= read(fd
, cp
, TMP_BUFSIZ
);
1043 len
= (size_t)(el
->el_line
.lastchar
-
1044 el
->el_line
.buffer
);
1045 len
= ct_mbstowcs(el
->el_line
.buffer
, cp
, len
);
1046 if (len
> 0 && el
->el_line
.buffer
[len
-1] == '\n')
1051 el
->el_line
.cursor
= el
->el_line
.buffer
;
1052 el
->el_line
.lastchar
= el
->el_line
.buffer
+ len
;
1060 /* return CC_REFRESH; */
1061 return ed_newline(el
, 0);
1070 /* vi_history_word():
1071 * Vi append word from previous input line
1073 * Who knows where this one came from!
1074 * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
1076 protected el_action_t
1078 vi_history_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
1080 const Char
*wp
= HIST_FIRST(el
);
1081 const Char
*wep
, *wsp
;
1091 while (Isspace(*wp
))
1096 while (*wp
&& !Isspace(*wp
))
1099 } while ((!el
->el_state
.doingarg
|| --el
->el_state
.argument
> 0)
1102 if (wsp
== 0 || (el
->el_state
.doingarg
&& el
->el_state
.argument
!= 0))
1106 len
= (int)(wep
- wsp
);
1107 if (el
->el_line
.cursor
< el
->el_line
.lastchar
)
1108 el
->el_line
.cursor
++;
1109 c_insert(el
, len
+ 1);
1110 cp
= el
->el_line
.cursor
;
1111 lim
= el
->el_line
.limit
;
1114 while (wsp
< wep
&& cp
< lim
)
1116 el
->el_line
.cursor
= cp
;
1118 el
->el_map
.current
= el
->el_map
.key
;
1123 * Vi redo last non-motion command
1126 protected el_action_t
1128 vi_redo(EditLine
*el
, Int c
__attribute__((__unused__
)))
1130 c_redo_t
*r
= &el
->el_chared
.c_redo
;
1132 if (!el
->el_state
.doingarg
&& r
->count
) {
1133 el
->el_state
.doingarg
= 1;
1134 el
->el_state
.argument
= r
->count
;
1137 el
->el_chared
.c_vcmd
.pos
= el
->el_line
.cursor
;
1138 el
->el_chared
.c_vcmd
.action
= r
->action
;
1139 if (r
->pos
!= r
->buf
) {
1140 if (r
->pos
+ 1 > r
->lim
)
1142 r
->pos
= r
->lim
- 1;
1144 FUN(el
,push
)(el
, r
->buf
);
1147 el
->el_state
.thiscmd
= r
->cmd
;
1148 el
->el_state
.thisch
= r
->ch
;
1149 return (*el
->el_map
.func
[r
->cmd
])(el
, r
->ch
);