41 #if !defined(lint) && !defined(SCCSID)
43 static char sccsid[] =
"@(#)vi.c 8.1 (Berkeley) 6/4/93";
53 private el_action_t cv_action(
EditLine *, Int);
54 private el_action_t cv_paste(
EditLine *, Int);
63 if (el->el_chared.c_vcmd.action != NOP) {
65 if (c != (Int)el->el_chared.c_vcmd.action)
70 cv_yank(el, el->el_line.buffer,
71 (
int)(el->el_line.lastchar - el->el_line.buffer));
72 el->el_chared.c_vcmd.action = NOP;
73 el->el_chared.c_vcmd.pos = 0;
75 el->el_line.lastchar = el->el_line.buffer;
76 el->el_line.cursor = el->el_line.buffer;
79 el->el_map.current = el->el_map.key;
83 el->el_chared.c_vcmd.pos = el->el_line.cursor;
84 el->el_chared.c_vcmd.action = c;
95 size_t len = (size_t)(k->last - k->buf);
97 if (k->buf == NULL || len == 0)
100 (void) fprintf(el->el_errfile,
"Paste: \"%.*s\"\n", (
int)len, k->buf);
105 if (!c && el->el_line.cursor < el->el_line.lastchar)
106 el->el_line.cursor++;
108 c_insert(el, (
int)len);
109 if (el->el_line.cursor + len > el->el_line.lastchar)
111 (void) memcpy(el->el_line.cursor, k->buf, len *
112 sizeof(*el->el_line.cursor));
122 protected el_action_t
124 vi_paste_next(
EditLine *el, Int c __attribute__((__unused__)))
127 return cv_paste(el, 0);
135 protected el_action_t
137 vi_paste_prev(
EditLine *el, Int c __attribute__((__unused__)))
140 return cv_paste(el, 1);
148 protected el_action_t
150 vi_prev_big_word(
EditLine *el, Int c __attribute__((__unused__)))
153 if (el->el_line.cursor == el->el_line.buffer)
156 el->el_line.cursor = cv_prev_word(el->el_line.cursor,
158 el->el_state.argument,
161 if (el->el_chared.c_vcmd.action != NOP) {
173 protected el_action_t
175 vi_prev_word(
EditLine *el, Int c __attribute__((__unused__)))
178 if (el->el_line.cursor == el->el_line.buffer)
181 el->el_line.cursor = cv_prev_word(el->el_line.cursor,
183 el->el_state.argument,
186 if (el->el_chared.c_vcmd.action != NOP) {
198 protected el_action_t
200 vi_next_big_word(
EditLine *el, Int c __attribute__((__unused__)))
203 if (el->el_line.cursor >= el->el_line.lastchar - 1)
206 el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
207 el->el_line.lastchar, el->el_state.argument, cv__isWord);
209 if (el->el_map.type == MAP_VI)
210 if (el->el_chared.c_vcmd.action != NOP) {
222 protected el_action_t
224 vi_next_word(
EditLine *el, Int c __attribute__((__unused__)))
227 if (el->el_line.cursor >= el->el_line.lastchar - 1)
230 el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
231 el->el_line.lastchar, el->el_state.argument, cv__isword);
233 if (el->el_map.type == MAP_VI)
234 if (el->el_chared.c_vcmd.action != NOP) {
246 protected el_action_t
251 if (el->el_line.cursor >= el->el_line.lastchar)
254 for (i = 0; i < el->el_state.argument; i++) {
256 c = *el->el_line.cursor;
258 *el->el_line.cursor = Tolower(c);
260 *el->el_line.cursor = Toupper(c);
262 if (++el->el_line.cursor >= el->el_line.lastchar) {
263 el->el_line.cursor--;
277 protected el_action_t
279 vi_change_meta(
EditLine *el, Int c __attribute__((__unused__)))
286 return cv_action(el, DELETE | INSERT);
294 protected el_action_t
296 vi_insert_at_bol(
EditLine *el, Int c __attribute__((__unused__)))
299 el->el_line.cursor = el->el_line.buffer;
301 el->el_map.current = el->el_map.key;
310 protected el_action_t
312 vi_replace_char(
EditLine *el, Int c __attribute__((__unused__)))
315 if (el->el_line.cursor >= el->el_line.lastchar)
318 el->el_map.current = el->el_map.key;
319 el->el_state.inputmode = MODE_REPLACE_1;
329 protected el_action_t
331 vi_replace_mode(
EditLine *el, Int c __attribute__((__unused__)))
334 el->el_map.current = el->el_map.key;
335 el->el_state.inputmode = MODE_REPLACE;
345 protected el_action_t
347 vi_substitute_char(
EditLine *el, Int c __attribute__((__unused__)))
350 c_delafter(el, el->el_state.argument);
351 el->el_map.current = el->el_map.key;
360 protected el_action_t
362 vi_substitute_line(
EditLine *el, Int c __attribute__((__unused__)))
366 cv_yank(el, el->el_line.buffer,
367 (
int)(el->el_line.lastchar - el->el_line.buffer));
368 (void) em_kill_line(el, 0);
369 el->el_map.current = el->el_map.key;
378 protected el_action_t
380 vi_change_to_eol(
EditLine *el, Int c __attribute__((__unused__)))
384 cv_yank(el, el->el_line.cursor,
385 (
int)(el->el_line.lastchar - el->el_line.cursor));
386 (void) ed_kill_line(el, 0);
387 el->el_map.current = el->el_map.key;
396 protected el_action_t
398 vi_insert(
EditLine *el, Int c __attribute__((__unused__)))
401 el->el_map.current = el->el_map.key;
411 protected el_action_t
413 vi_add(
EditLine *el, Int c __attribute__((__unused__)))
417 el->el_map.current = el->el_map.key;
418 if (el->el_line.cursor < el->el_line.lastchar) {
419 el->el_line.cursor++;
420 if (el->el_line.cursor > el->el_line.lastchar)
421 el->el_line.cursor = el->el_line.lastchar;
428 return (el_action_t)
ret;
436 protected el_action_t
438 vi_add_at_eol(
EditLine *el, Int c __attribute__((__unused__)))
441 el->el_map.current = el->el_map.key;
442 el->el_line.cursor = el->el_line.lastchar;
452 protected el_action_t
454 vi_delete_meta(
EditLine *el, Int c __attribute__((__unused__)))
457 return cv_action(el, DELETE);
465 protected el_action_t
467 vi_end_big_word(
EditLine *el, Int c __attribute__((__unused__)))
470 if (el->el_line.cursor == el->el_line.lastchar)
473 el->el_line.cursor = cv__endword(el->el_line.cursor,
474 el->el_line.lastchar, el->el_state.argument, cv__isWord);
476 if (el->el_chared.c_vcmd.action != NOP) {
477 el->el_line.cursor++;
489 protected el_action_t
491 vi_end_word(
EditLine *el, Int c __attribute__((__unused__)))
494 if (el->el_line.cursor == el->el_line.lastchar)
497 el->el_line.cursor = cv__endword(el->el_line.cursor,
498 el->el_line.lastchar, el->el_state.argument, cv__isword);
500 if (el->el_chared.c_vcmd.action != NOP) {
501 el->el_line.cursor++;
513 protected el_action_t
515 vi_undo(
EditLine *el, Int c __attribute__((__unused__)))
523 el->el_chared.c_undo.buf = el->el_line.buffer;
524 el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
525 el->el_chared.c_undo.cursor =
526 (int)(el->el_line.cursor - el->el_line.buffer);
527 el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
528 el->el_line.buffer = un.buf;
529 el->el_line.cursor = un.buf + un.cursor;
530 el->el_line.lastchar = un.buf + un.len;
540 protected el_action_t
542 vi_command_mode(
EditLine *el, Int c __attribute__((__unused__)))
546 el->el_chared.c_vcmd.action = NOP;
547 el->el_chared.c_vcmd.pos = 0;
549 el->el_state.doingarg = 0;
551 el->el_state.inputmode = MODE_INSERT;
552 el->el_map.current = el->el_map.alt;
554 if (el->el_line.cursor > el->el_line.buffer)
555 el->el_line.cursor--;
565 protected el_action_t
569 if (el->el_state.doingarg)
570 return ed_argument_digit(el, c);
572 el->el_line.cursor = el->el_line.buffer;
573 if (el->el_chared.c_vcmd.action != NOP) {
585 protected el_action_t
587 vi_delete_prev_char(
EditLine *el, Int c __attribute__((__unused__)))
590 if (el->el_line.cursor <= el->el_line.buffer)
594 el->el_line.cursor--;
603 protected el_action_t
608 if (el->el_line.cursor == el->el_line.lastchar) {
609 if (el->el_line.cursor == el->el_line.buffer) {
610 terminal_writec(el, c);
623 *el->el_line.lastchar =
'\0';
624 return CC_LIST_CHOICES;
640 protected el_action_t
642 vi_kill_line_prev(
EditLine *el, Int c __attribute__((__unused__)))
646 cp = el->el_line.buffer;
647 kp = el->el_chared.c_kill.buf;
648 while (cp < el->el_line.cursor)
650 el->el_chared.c_kill.last = kp;
651 c_delbefore(el, (
int)(el->el_line.cursor - el->el_line.buffer));
652 el->el_line.cursor = el->el_line.buffer;
661 protected el_action_t
663 vi_search_prev(
EditLine *el, Int c __attribute__((__unused__)))
666 return cv_search(el, ED_SEARCH_PREV_HISTORY);
674 protected el_action_t
676 vi_search_next(
EditLine *el, Int c __attribute__((__unused__)))
679 return cv_search(el, ED_SEARCH_NEXT_HISTORY);
687 protected el_action_t
689 vi_repeat_search_next(
EditLine *el, Int c __attribute__((__unused__)))
692 if (el->el_search.patlen == 0)
695 return cv_repeat_srch(el, el->el_search.patdir);
704 protected el_action_t
705 vi_repeat_search_prev(
EditLine *el, Int c __attribute__((__unused__)))
708 if (el->el_search.patlen == 0)
711 return (cv_repeat_srch(el,
712 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
713 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
721 protected el_action_t
723 vi_next_char(
EditLine *el, Int c __attribute__((__unused__)))
725 return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
733 protected el_action_t
735 vi_prev_char(
EditLine *el, Int c __attribute__((__unused__)))
737 return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
745 protected el_action_t
747 vi_to_next_char(
EditLine *el, Int c __attribute__((__unused__)))
749 return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
757 protected el_action_t
759 vi_to_prev_char(
EditLine *el, Int c __attribute__((__unused__)))
761 return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
769 protected el_action_t
771 vi_repeat_next_char(
EditLine *el, Int c __attribute__((__unused__)))
774 return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
775 el->el_state.argument, el->el_search.chatflg);
783 protected el_action_t
785 vi_repeat_prev_char(
EditLine *el, Int c __attribute__((__unused__)))
788 int dir = el->el_search.chadir;
790 r = cv_csearch(el, -dir, el->el_search.chacha,
791 el->el_state.argument, el->el_search.chatflg);
792 el->el_search.chadir = dir;
801 protected el_action_t
803 vi_match(
EditLine *el, Int c __attribute__((__unused__)))
805 const Char match_chars[] = STR(
"()[]{}");
807 size_t delta,
i, count;
810 *el->el_line.lastchar =
'\0';
812 i = Strcspn(el->el_line.cursor, match_chars);
813 o_ch = el->el_line.cursor[
i];
816 delta = (size_t)(Strchr(match_chars, o_ch) - match_chars);
817 c_ch = match_chars[delta ^ 1];
819 delta = 1 - (delta & 1) * 2;
821 for (cp = &el->el_line.cursor[i]; count; ) {
823 if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
827 else if (*cp == c_ch)
831 el->el_line.cursor = cp;
833 if (el->el_chared.c_vcmd.action != NOP) {
837 el->el_line.cursor++;
848 protected el_action_t
850 vi_undo_line(
EditLine *el, Int c __attribute__((__unused__)))
862 protected el_action_t
864 vi_to_column(
EditLine *el, Int c __attribute__((__unused__)))
867 el->el_line.cursor = el->el_line.buffer;
868 el->el_state.argument--;
869 return ed_next_char(el, 0);
876 protected el_action_t
878 vi_yank_end(
EditLine *el, Int c __attribute__((__unused__)))
881 cv_yank(el, el->el_line.cursor,
882 (
int)(el->el_line.lastchar - el->el_line.cursor));
890 protected el_action_t
892 vi_yank(
EditLine *el, Int c __attribute__((__unused__)))
895 return cv_action(el, YANK);
902 protected el_action_t
904 vi_comment_out(
EditLine *el, Int c __attribute__((__unused__)))
907 el->el_line.cursor = el->el_line.buffer;
909 *el->el_line.cursor =
'#';
911 return ed_newline(el, 0);
920 #if defined(__weak_reference) && !defined(__FreeBSD__)
921 __weakref_visible
char *my_get_alias_text(
const char *)
922 __weak_reference(get_alias_text);
924 protected el_action_t
926 vi_alias(
EditLine *el __attribute__((__unused__)),
927 Int c __attribute__((__unused__)))
929 #if defined(__weak_reference) && !defined(__FreeBSD__)
933 if (my_get_alias_text == 0) {
939 if (el_getc(el, &alias_name[1]) != 1)
942 alias_text = my_get_alias_text(alias_name);
943 if (alias_text != NULL)
944 FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch));
955 protected el_action_t
957 vi_to_history_line(
EditLine *el, Int c __attribute__((__unused__)))
959 int sv_event_no = el->el_history.eventno;
963 if (el->el_history.eventno == 0) {
964 (void) Strncpy(el->el_history.buf, el->el_line.buffer,
966 el->el_history.last = el->el_history.buf +
967 (el->el_line.lastchar - el->el_line.buffer);
971 if (!el->el_state.doingarg) {
972 el->el_history.eventno = 0x7fffffff;
980 el->el_history.eventno = 1;
981 if (hist_get(el) == CC_ERROR)
983 el->el_history.eventno = 1 + el->el_history.ev.num
984 - el->el_state.argument;
985 if (el->el_history.eventno < 0) {
986 el->el_history.eventno = sv_event_no;
991 if (rval == CC_ERROR)
992 el->el_history.eventno = sv_event_no;
1000 protected el_action_t
1002 vi_histedit(
EditLine *el, Int c __attribute__((__unused__)))
1008 char tempfile[] =
"/tmp/histedit.XXXXXXXXXX";
1014 memset(&state, 0,
sizeof(mbstate_t));
1015 if (el->el_state.doingarg) {
1016 if (vi_to_history_line(el, 0) == CC_ERROR)
1020 fd = mkstemp(tempfile);
1023 len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
1024 #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
1025 cp = el_malloc(TMP_BUFSIZ *
sizeof(*cp));
1032 line = el_malloc((len+1) *
sizeof(*line));
1037 Strncpy(line, el->el_line.buffer, len);
1039 wcsrtombs(cp, (
const wchar_t **) &line, TMP_BUFSIZ - 1, &state);
1040 cp[TMP_BUFSIZ - 1] =
'\0';
1042 if (write(fd, cp, len) == -1)
1044 if (write(fd,
"\n", (
size_t)1) == -1)
1056 execlp(
"vi",
"vi", tempfile, (
char *)NULL);
1060 while (waitpid(pid, &status, 0) != pid)
1062 lseek(fd, (off_t)0, SEEK_SET);
1063 st = read(fd, cp, TMP_BUFSIZ);
1065 len = (size_t)(el->el_line.lastchar -
1066 el->el_line.buffer);
1067 memset(&state, 0,
sizeof(mbstate_t));
1068 len = mbsrtowcs(el->el_line.buffer,
1069 (
const char**) &cp, len, &state);
1070 if (len > 0 && el->el_line.buffer[len -1] ==
'\n')
1075 el->el_line.cursor = el->el_line.buffer;
1076 el->el_line.lastchar = el->el_line.buffer + len;
1085 return ed_newline(el, 0);
1100 protected el_action_t
1102 vi_history_word(
EditLine *el, Int c __attribute__((__unused__)))
1104 const Char *wp = HIST_FIRST(el);
1105 const Char *wep, *wsp;
1115 while (Isspace(*wp))
1120 while (*wp && !Isspace(*wp))
1123 }
while ((!el->el_state.doingarg || --el->el_state.argument > 0)
1126 if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
1130 len = (int)(wep - wsp);
1131 if (el->el_line.cursor < el->el_line.lastchar)
1132 el->el_line.cursor++;
1133 c_insert(el, len + 1);
1134 cp = el->el_line.cursor;
1135 lim = el->el_line.limit;
1138 while (wsp < wep && cp < lim)
1140 el->el_line.cursor = cp;
1142 el->el_map.current = el->el_map.key;
1150 protected el_action_t
1152 vi_redo(
EditLine *el, Int c __attribute__((__unused__)))
1154 c_redo_t *r = &el->el_chared.c_redo;
1156 if (!el->el_state.doingarg && r->count) {
1157 el->el_state.doingarg = 1;
1158 el->el_state.argument = r->count;
1161 el->el_chared.c_vcmd.pos = el->el_line.cursor;
1162 el->el_chared.c_vcmd.action = r->action;
1163 if (r->pos != r->buf) {
1164 if (r->pos + 1 > r->lim)
1166 r->pos = r->lim - 1;
1168 FUN(el,push)(el, r->buf);
1171 el->el_state.thiscmd = r->cmd;
1172 el->el_state.thisch = r->ch;
1173 return (*el->el_map.func[r->cmd])(el, r->ch);