diff options
Diffstat (limited to 'cmd-line-utils/libedit/vi.c')
-rw-r--r-- | cmd-line-utils/libedit/vi.c | 735 |
1 files changed, 461 insertions, 274 deletions
diff --git a/cmd-line-utils/libedit/vi.c b/cmd-line-utils/libedit/vi.c index 296e11eb4d9..5380872cf65 100644 --- a/cmd-line-utils/libedit/vi.c +++ b/cmd-line-utils/libedit/vi.c @@ -1,4 +1,4 @@ -/* $NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $ */ +/* $NetBSD: vi.c,v 1.16 2003/03/10 11:09:25 dsl Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -36,12 +36,22 @@ * SUCH DAMAGE. */ -#include "compat.h" +#include "config.h" +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> + +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: vi.c,v 1.16 2003/03/10 11:09:25 dsl Exp $"); +#endif +#endif /* not lint && not SCCSID */ /* * vi.c: Vi mode commands. */ -#include "sys.h" #include "el.h" private el_action_t cv_action(EditLine *, int); @@ -53,22 +63,18 @@ private el_action_t cv_paste(EditLine *, int); private el_action_t cv_action(EditLine *el, int c) { - char *cp, *kp; - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { + /* 'cc', 'dd' and (possibly) friends */ + if (c != el->el_chared.c_vcmd.action) + return CC_ERROR; + + if (!(c & YANK)) + cv_undo(el); + cv_yank(el, el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = 0; - - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - kp = el->el_chared.c_undo.buf; - for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) { - *kp++ = *cp; - el->el_chared.c_undo.dsize++; - } - - el->el_chared.c_undo.action = INSERT; - el->el_chared.c_undo.ptr = el->el_line.buffer; el->el_line.lastchar = el->el_line.buffer; el->el_line.cursor = el->el_line.buffer; if (c & INSERT) @@ -79,25 +85,8 @@ cv_action(EditLine *el, int c) el->el_chared.c_vcmd.pos = el->el_line.cursor; el->el_chared.c_vcmd.action = c; return (CC_ARGHACK); - -#ifdef notdef - /* - * I don't think that this is needed. But we keep it for now - */ - else - if (el_chared.c_vcmd.action == NOP) { - el->el_chared.c_vcmd.pos = el->el_line.cursor; - el->el_chared.c_vcmd.action = c; - return (CC_ARGHACK); - } else { - el->el_chared.c_vcmd.action = 0; - el->el_chared.c_vcmd.pos = 0; - return (CC_ERROR); - } -#endif } - /* cv_paste(): * Paste previous deletion before or after the cursor */ @@ -105,23 +94,25 @@ private el_action_t cv_paste(EditLine *el, int c) { char *ptr; - c_undo_t *un = &el->el_chared.c_undo; + c_kill_t *k = &el->el_chared.c_kill; + int len = k->last - k->buf; + if (k->buf == NULL || len == 0) + return (CC_ERROR); #ifdef DEBUG_PASTE - (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n", - un->action, un->buf, un->isize, un->dsize); + (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf); #endif - if (un->isize == 0) - return (CC_ERROR); + + cv_undo(el); if (!c && el->el_line.cursor < el->el_line.lastchar) el->el_line.cursor++; ptr = el->el_line.cursor; - c_insert(el, (int) un->isize); - if (el->el_line.cursor + un->isize > el->el_line.lastchar) + c_insert(el, len); + if (el->el_line.cursor + len > el->el_line.lastchar) return (CC_ERROR); - (void) memcpy(ptr, un->buf, un->isize); + (void) memcpy(ptr, k->buf, len +0u); return (CC_REFRESH); } @@ -152,24 +143,24 @@ vi_paste_prev(EditLine *el, int c __attribute__((unused))) } -/* vi_prev_space_word(): +/* vi_prev_big_word(): * Vi move to the previous space delimited word * [B] */ protected el_action_t /*ARGSUSED*/ -vi_prev_space_word(EditLine *el, int c __attribute__((unused))) +vi_prev_big_word(EditLine *el, int c __attribute__((unused))) { if (el->el_line.cursor == el->el_line.buffer) return (CC_ERROR); - el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, + el->el_line.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, - cv__isword); + cv__isWord); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -179,7 +170,7 @@ vi_prev_space_word(EditLine *el, int c __attribute__((unused))) /* vi_prev_word(): * Vi move to the previous word - * [B] + * [b] */ protected el_action_t /*ARGSUSED*/ @@ -189,12 +180,12 @@ vi_prev_word(EditLine *el, int c __attribute__((unused))) if (el->el_line.cursor == el->el_line.buffer) return (CC_ERROR); - el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, + el->el_line.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, - ce__isword); + cv__isword); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -202,25 +193,23 @@ vi_prev_word(EditLine *el, int c __attribute__((unused))) } -/* vi_next_space_word(): +/* vi_next_big_word(): * Vi move to the next space delimited word * [W] */ protected el_action_t /*ARGSUSED*/ -vi_next_space_word(EditLine *el, int c __attribute__((unused))) +vi_next_big_word(EditLine *el, int c __attribute__((unused))) { - if (el->el_line.cursor == el->el_line.lastchar) + if (el->el_line.cursor >= el->el_line.lastchar - 1) return (CC_ERROR); el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - cv__isword); + el->el_line.lastchar, el->el_state.argument, cv__isWord); if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -237,16 +226,14 @@ protected el_action_t vi_next_word(EditLine *el, int c __attribute__((unused))) { - if (el->el_line.cursor == el->el_line.lastchar) + if (el->el_line.cursor >= el->el_line.lastchar - 1) return (CC_ERROR); el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - ce__isword); + el->el_line.lastchar, el->el_state.argument, cv__isword); if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } @@ -261,19 +248,27 @@ vi_next_word(EditLine *el, int c __attribute__((unused))) protected el_action_t vi_change_case(EditLine *el, int c) { + int i; - if (el->el_line.cursor < el->el_line.lastchar) { - c = *el->el_line.cursor; + if (el->el_line.cursor >= el->el_line.lastchar) + return (CC_ERROR); + cv_undo(el); + for (i = 0; i < el->el_state.argument; i++) { + + c = *(unsigned char *)el->el_line.cursor; if (isupper(c)) - *el->el_line.cursor++ = tolower(c); + *el->el_line.cursor = tolower(c); else if (islower(c)) - *el->el_line.cursor++ = toupper(c); - else - el->el_line.cursor++; + *el->el_line.cursor = toupper(c); + + if (++el->el_line.cursor >= el->el_line.lastchar) { + el->el_line.cursor--; + re_fastaddc(el); + break; + } re_fastaddc(el); - return (CC_NORM); } - return (CC_ERROR); + return CC_NORM; } @@ -304,11 +299,7 @@ vi_insert_at_bol(EditLine *el, int c __attribute__((unused))) { el->el_line.cursor = el->el_line.buffer; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; - + cv_undo(el); el->el_map.current = el->el_map.key; return (CC_CURSOR); } @@ -323,13 +314,13 @@ protected el_action_t vi_replace_char(EditLine *el, int c __attribute__((unused))) { + if (el->el_line.cursor >= el->el_line.lastchar) + return CC_ERROR; + el->el_map.current = el->el_map.key; el->el_state.inputmode = MODE_REPLACE_1; - el->el_chared.c_undo.action = CHANGE; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; - return (CC_NORM); + cv_undo(el); + return (CC_ARGHACK); } @@ -344,17 +335,14 @@ vi_replace_mode(EditLine *el, int c __attribute__((unused))) el->el_map.current = el->el_map.key; el->el_state.inputmode = MODE_REPLACE; - el->el_chared.c_undo.action = CHANGE; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.isize = 0; - el->el_chared.c_undo.dsize = 0; + cv_undo(el); return (CC_NORM); } /* vi_substitute_char(): * Vi replace character under the cursor and enter insert mode - * [r] + * [s] */ protected el_action_t /*ARGSUSED*/ @@ -376,6 +364,9 @@ protected el_action_t vi_substitute_line(EditLine *el, int c __attribute__((unused))) { + cv_undo(el); + cv_yank(el, el->el_line.buffer, + el->el_line.lastchar - el->el_line.buffer); (void) em_kill_line(el, 0); el->el_map.current = el->el_map.key; return (CC_REFRESH); @@ -391,6 +382,9 @@ protected el_action_t vi_change_to_eol(EditLine *el, int c __attribute__((unused))) { + cv_undo(el); + cv_yank(el, el->el_line.cursor, + el->el_line.lastchar - el->el_line.cursor); (void) ed_kill_line(el, 0); el->el_map.current = el->el_map.key; return (CC_REFRESH); @@ -407,11 +401,7 @@ vi_insert(EditLine *el, int c __attribute__((unused))) { el->el_map.current = el->el_map.key; - - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; - + cv_undo(el); return (CC_NORM); } @@ -435,9 +425,7 @@ vi_add(EditLine *el, int c __attribute__((unused))) } else ret = CC_NORM; - el->el_chared.c_vcmd.ins = el->el_line.cursor; - el->el_chared.c_undo.ptr = el->el_line.cursor; - el->el_chared.c_undo.action = DELETE; + cv_undo(el); return (ret); } @@ -454,11 +442,7 @@ vi_add_at_eol(EditLine *el, int c __attribute__((unused))) el->el_map.current = el->el_map.key; el->el_line.cursor = el->el_line.lastchar; - - /* Mark where insertion begins */ - el->el_chared.c_vcmd.ins = el->el_line.lastchar; - el->el_chared.c_undo.ptr = el->el_line.lastchar; - el->el_chared.c_undo.action = DELETE; + cv_undo(el); return (CC_CURSOR); } @@ -476,22 +460,22 @@ vi_delete_meta(EditLine *el, int c __attribute__((unused))) } -/* vi_end_word(): +/* vi_end_big_word(): * Vi move to the end of the current space delimited word * [E] */ protected el_action_t /*ARGSUSED*/ -vi_end_word(EditLine *el, int c __attribute__((unused))) +vi_end_big_word(EditLine *el, int c __attribute__((unused))) { if (el->el_line.cursor == el->el_line.lastchar) return (CC_ERROR); el->el_line.cursor = cv__endword(el->el_line.cursor, - el->el_line.lastchar, el->el_state.argument); + el->el_line.lastchar, el->el_state.argument, cv__isWord); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); return (CC_REFRESH); @@ -500,22 +484,22 @@ vi_end_word(EditLine *el, int c __attribute__((unused))) } -/* vi_to_end_word(): +/* vi_end_word(): * Vi move to the end of the current word * [e] */ protected el_action_t /*ARGSUSED*/ -vi_to_end_word(EditLine *el, int c __attribute__((unused))) +vi_end_word(EditLine *el, int c __attribute__((unused))) { if (el->el_line.cursor == el->el_line.lastchar) return (CC_ERROR); el->el_line.cursor = cv__endword(el->el_line.cursor, - el->el_line.lastchar, el->el_state.argument); + el->el_line.lastchar, el->el_state.argument, cv__isword); - if (el->el_chared.c_vcmd.action & DELETE) { + if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); return (CC_REFRESH); @@ -532,100 +516,19 @@ protected el_action_t /*ARGSUSED*/ vi_undo(EditLine *el, int c __attribute__((unused))) { - char *cp, *kp; - char temp; - int i, size; - c_undo_t *un = &el->el_chared.c_undo; - -#ifdef DEBUG_UNDO - (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n", - un->action, un->buf, un->isize, un->dsize); -#endif - switch (un->action) { - case DELETE: - if (un->dsize == 0) - return (CC_NORM); - - (void) memcpy(un->buf, un->ptr, un->dsize); - for (cp = un->ptr; cp <= el->el_line.lastchar; cp++) - *cp = cp[un->dsize]; - - el->el_line.lastchar -= un->dsize; - el->el_line.cursor = un->ptr; - - un->action = INSERT; - un->isize = un->dsize; - un->dsize = 0; - break; + c_undo_t un = el->el_chared.c_undo; - case DELETE | INSERT: - size = un->isize - un->dsize; - if (size > 0) - i = un->dsize; - else - i = un->isize; - cp = un->ptr; - kp = un->buf; - while (i-- > 0) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - if (size > 0) { - el->el_line.cursor = cp; - c_insert(el, size); - while (size-- > 0 && cp < el->el_line.lastchar) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - } else if (size < 0) { - size = -size; - for (; cp <= el->el_line.lastchar; cp++) { - *kp++ = *cp; - *cp = cp[size]; - } - el->el_line.lastchar -= size; - } - el->el_line.cursor = un->ptr; - i = un->dsize; - un->dsize = un->isize; - un->isize = i; - break; - - case INSERT: - if (un->isize == 0) - return (CC_NORM); - - el->el_line.cursor = un->ptr; - c_insert(el, (int) un->isize); - (void) memcpy(un->ptr, un->buf, un->isize); - un->action = DELETE; - un->dsize = un->isize; - un->isize = 0; - break; + if (un.len == -1) + return CC_ERROR; - case CHANGE: - if (un->isize == 0) - return (CC_NORM); - - el->el_line.cursor = un->ptr; - size = (int) (el->el_line.cursor - el->el_line.lastchar); - if (size < (int)un->isize) - size = un->isize; - cp = un->ptr; - kp = un->buf; - for (i = 0; i < size; i++) { - temp = *kp; - *kp++ = *cp; - *cp++ = temp; - } - un->dsize = 0; - break; - - default: - return (CC_ERROR); - } + /* switch line buffer and undo buffer */ + el->el_chared.c_undo.buf = el->el_line.buffer; + el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; + el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer; + el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); + el->el_line.buffer = un.buf; + el->el_line.cursor = un.buf + un.cursor; + el->el_line.lastchar = un.buf + un.len; return (CC_REFRESH); } @@ -639,22 +542,12 @@ protected el_action_t /*ARGSUSED*/ vi_command_mode(EditLine *el, int c __attribute__((unused))) { - int size; /* [Esc] cancels pending action */ - el->el_chared.c_vcmd.ins = 0; el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = 0; el->el_state.doingarg = 0; - size = el->el_chared.c_undo.ptr - el->el_line.cursor; - if (size < 0) - size = -size; - if (el->el_chared.c_undo.action == (INSERT | DELETE) || - el->el_chared.c_undo.action == DELETE) - el->el_chared.c_undo.dsize = size; - else - el->el_chared.c_undo.isize = size; el->el_state.inputmode = MODE_INSERT; el->el_map.current = el->el_map.alt; @@ -674,41 +567,37 @@ protected el_action_t vi_zero(EditLine *el, int c) { - if (el->el_state.doingarg) { - if (el->el_state.argument > 1000000) - return (CC_ERROR); - el->el_state.argument = - (el->el_state.argument * 10) + (c - '0'); - return (CC_ARGHACK); - } else { - el->el_line.cursor = el->el_line.buffer; - if (el->el_chared.c_vcmd.action & DELETE) { - cv_delfini(el); - return (CC_REFRESH); - } - return (CC_CURSOR); + if (el->el_state.doingarg) + return ed_argument_digit(el, c); + + el->el_line.cursor = el->el_line.buffer; + if (el->el_chared.c_vcmd.action != NOP) { + cv_delfini(el); + return (CC_REFRESH); } + return (CC_CURSOR); } /* vi_delete_prev_char(): * Vi move to previous character (backspace) - * [^H] + * [^H] in insert mode only */ protected el_action_t /*ARGSUSED*/ vi_delete_prev_char(EditLine *el, int c __attribute__((unused))) { + char *cp; - if (el->el_chared.c_vcmd.ins == 0) + cp = el->el_line.cursor; + if (cp <= el->el_line.buffer) return (CC_ERROR); - if (el->el_chared.c_vcmd.ins > - el->el_line.cursor - el->el_state.argument) - return (CC_ERROR); - - c_delbefore(el, el->el_state.argument); - el->el_line.cursor -= el->el_state.argument; + /* do the delete here so we dont mess up the undo and paste buffers */ + el->el_line.cursor = --cp; + for (; cp < el->el_line.lastchar; cp++) + cp[0] = cp[1]; + el->el_line.lastchar = cp - 1; return (CC_REFRESH); } @@ -829,16 +718,7 @@ protected el_action_t /*ARGSUSED*/ vi_next_char(EditLine *el, int c __attribute__((unused))) { - char ch; - - if (el_getc(el, &ch) != 1) - return (ed_end_of_file(el, 0)); - - el->el_search.chadir = CHAR_FWD; - el->el_search.chacha = ch; - - return (cv_csearch_fwd(el, ch, el->el_state.argument, 0)); - + return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); } @@ -850,15 +730,7 @@ protected el_action_t /*ARGSUSED*/ vi_prev_char(EditLine *el, int c __attribute__((unused))) { - char ch; - - if (el_getc(el, &ch) != 1) - return (ed_end_of_file(el, 0)); - - el->el_search.chadir = CHAR_BACK; - el->el_search.chacha = ch; - - return (cv_csearch_back(el, ch, el->el_state.argument, 0)); + return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); } @@ -870,13 +742,7 @@ protected el_action_t /*ARGSUSED*/ vi_to_next_char(EditLine *el, int c __attribute__((unused))) { - char ch; - - if (el_getc(el, &ch) != 1) - return (ed_end_of_file(el, 0)); - - return (cv_csearch_fwd(el, ch, el->el_state.argument, 1)); - + return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); } @@ -888,12 +754,7 @@ protected el_action_t /*ARGSUSED*/ vi_to_prev_char(EditLine *el, int c __attribute__((unused))) { - char ch; - - if (el_getc(el, &ch) != 1) - return (ed_end_of_file(el, 0)); - - return (cv_csearch_back(el, ch, el->el_state.argument, 1)); + return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); } @@ -906,14 +767,8 @@ protected el_action_t vi_repeat_next_char(EditLine *el, int c __attribute__((unused))) { - if (el->el_search.chacha == 0) - return (CC_ERROR); - - return (el->el_search.chadir == CHAR_FWD - ? cv_csearch_fwd(el, el->el_search.chacha, - el->el_state.argument, 0) - : cv_csearch_back(el, el->el_search.chacha, - el->el_state.argument, 0)); + return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, + el->el_state.argument, el->el_search.chatflg); } @@ -925,11 +780,343 @@ protected el_action_t /*ARGSUSED*/ vi_repeat_prev_char(EditLine *el, int c __attribute__((unused))) { + el_action_t r; + int dir = el->el_search.chadir; - if (el->el_search.chacha == 0) - return (CC_ERROR); + r = cv_csearch(el, -dir, el->el_search.chacha, + el->el_state.argument, el->el_search.chatflg); + el->el_search.chadir = dir; + return r; +} + + +/* vi_match(): + * Vi go to matching () {} or [] + * [%] + */ +protected el_action_t +/*ARGSUSED*/ +vi_match(EditLine *el, int c __attribute__((unused))) +{ + const char match_chars[] = "()[]{}"; + char *cp; + int delta, i, count; + char o_ch, c_ch; + + *el->el_line.lastchar = '\0'; /* just in case */ + + i = strcspn(el->el_line.cursor, match_chars); + o_ch = el->el_line.cursor[i]; + if (o_ch == 0) + return CC_ERROR; + delta = strchr(match_chars, o_ch) - match_chars; + c_ch = match_chars[delta ^ 1]; + count = 1; + delta = 1 - (delta & 1) * 2; + + for (cp = &el->el_line.cursor[i]; count; ) { + cp += delta; + if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) + return CC_ERROR; + if (*cp == o_ch) + count++; + else if (*cp == c_ch) + count--; + } + + el->el_line.cursor = cp; + + if (el->el_chared.c_vcmd.action != NOP) { + /* NB posix says char under cursor should NOT be deleted + for -ve delta - this is different to netbsd vi. */ + if (delta > 0) + el->el_line.cursor++; + cv_delfini(el); + return (CC_REFRESH); + } + return (CC_CURSOR); +} + +/* vi_undo_line(): + * Vi undo all changes to line + * [U] + */ +protected el_action_t +/*ARGSUSED*/ +vi_undo_line(EditLine *el, int c __attribute__((unused))) +{ + + cv_undo(el); + return hist_get(el); +} + +/* vi_to_column(): + * Vi go to specified column + * [|] + * NB netbsd vi goes to screen column 'n', posix says nth character + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_column(EditLine *el, int c __attribute__((unused))) +{ + + el->el_line.cursor = el->el_line.buffer; + el->el_state.argument--; + return ed_next_char(el, 0); +} + +/* vi_yank_end(): + * Vi yank to end of line + * [Y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank_end(EditLine *el, int c __attribute__((unused))) +{ + + cv_yank(el, el->el_line.cursor, + el->el_line.lastchar - el->el_line.cursor); + return CC_REFRESH; +} + +/* vi_yank(): + * Vi yank + * [y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank(EditLine *el, int c __attribute__((unused))) +{ + + return cv_action(el, YANK); +} + +/* vi_comment_out(): + * Vi comment out current command + * [c] + */ +protected el_action_t +/*ARGSUSED*/ +vi_comment_out(EditLine *el, int c __attribute__((unused))) +{ + + el->el_line.cursor = el->el_line.buffer; + c_insert(el, 1); + *el->el_line.cursor = '#'; + re_refresh(el); + return ed_newline(el, 0); +} + +/* vi_alias(): + * Vi include shell alias + * [@] + * NB: posix impiles that we should enter insert mode, however + * this is against historical precedent... + */ +protected el_action_t +/*ARGSUSED*/ +vi_alias(EditLine *el __attribute__((unused)), int c __attribute__((unused))) +{ +#ifdef __weak_extern + char alias_name[3]; + char *alias_text; + extern char *get_alias_text(const char *); + __weak_extern(get_alias_text); + + if (get_alias_text == 0) { + return CC_ERROR; + } + + alias_name[0] = '_'; + alias_name[2] = 0; + if (el_getc(el, &alias_name[1]) != 1) + return CC_ERROR; + + alias_text = get_alias_text(alias_name); + if (alias_text != NULL) + el_push(el, alias_text); + return CC_NORM; +#else + return CC_ERROR; +#endif +} + +/* vi_to_history_line(): + * Vi go to specified history file line. + * [G] + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_history_line(EditLine *el, int c __attribute__((unused))) +{ + int sv_event_no = el->el_history.eventno; + el_action_t rval; + + + if (el->el_history.eventno == 0) { + (void) strncpy(el->el_history.buf, el->el_line.buffer, + EL_BUFSIZ); + el->el_history.last = el->el_history.buf + + (el->el_line.lastchar - el->el_line.buffer); + } + + /* Lack of a 'count' means oldest, not 1 */ + if (!el->el_state.doingarg) { + el->el_history.eventno = 0x7fffffff; + hist_get(el); + } else { + /* This is brain dead, all the rest of this code counts + * upwards going into the past. Here we need count in the + * other direction (to match the output of fc -l). + * I could change the world, but this seems to suffice. + */ + el->el_history.eventno = 1; + if (hist_get(el) == CC_ERROR) + return CC_ERROR; + el->el_history.eventno = 1 + el->el_history.ev.num + - el->el_state.argument; + if (el->el_history.eventno < 0) { + el->el_history.eventno = sv_event_no; + return CC_ERROR; + } + } + rval = hist_get(el); + if (rval == CC_ERROR) + el->el_history.eventno = sv_event_no; + return rval; +} + +/* vi_histedit(): + * Vi edit history line with vi + * [v] + */ +protected el_action_t +/*ARGSUSED*/ +vi_histedit(EditLine *el, int c __attribute__((unused))) +{ + int fd; + pid_t pid; + int st; + char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; + char *cp; + + if (el->el_state.doingarg) { + if (vi_to_history_line(el, 0) == CC_ERROR) + return CC_ERROR; + } + + fd = mkstemp(tempfile); + if (fd < 0) + return CC_ERROR; + cp = el->el_line.buffer; + write(fd, cp, el->el_line.lastchar - cp +0u); + write(fd, "\n", 1); + pid = fork(); + switch (pid) { + case -1: + close(fd); + unlink(tempfile); + return CC_ERROR; + case 0: + close(fd); + execlp("vi", "vi", tempfile, 0); + exit(0); + /*NOTREACHED*/ + default: + while (waitpid(pid, &st, 0) != pid) + continue; + lseek(fd, 0ll, SEEK_SET); + st = read(fd, cp, el->el_line.limit - cp +0u); + if (st > 0 && cp[st - 1] == '\n') + st--; + el->el_line.cursor = cp; + el->el_line.lastchar = cp + st; + break; + } + + close(fd); + unlink(tempfile); + /* return CC_REFRESH; */ + return ed_newline(el, 0); +} + +/* vi_history_word(): + * Vi append word from previous input line + * [_] + * Who knows where this one came from! + * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' + */ +protected el_action_t +/*ARGSUSED*/ +vi_history_word(EditLine *el, int c __attribute__((unused))) +{ + const char *wp = HIST_FIRST(el); + const char *wep, *wsp; + int len; + char *cp; + const char *lim; + + if (wp == NULL) + return CC_ERROR; + + wep = wsp = 0; + do { + while (isspace((unsigned char)*wp)) + wp++; + if (*wp == 0) + break; + wsp = wp; + while (*wp && !isspace((unsigned char)*wp)) + wp++; + wep = wp; + } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0); + + if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) + return CC_ERROR; + + cv_undo(el); + len = wep - wsp; + if (el->el_line.cursor < el->el_line.lastchar) + el->el_line.cursor++; + c_insert(el, len + 1); + cp = el->el_line.cursor; + lim = el->el_line.limit; + if (cp < lim) + *cp++ = ' '; + while (wsp < wep && cp < lim) + *cp++ = *wsp++; + el->el_line.cursor = cp; + + el->el_map.current = el->el_map.key; + return CC_REFRESH; +} + +/* vi_redo(): + * Vi redo last non-motion command + * [.] + */ +protected el_action_t +/*ARGSUSED*/ +vi_redo(EditLine *el, int c __attribute__((unused))) +{ + c_redo_t *r = &el->el_chared.c_redo; + + if (!el->el_state.doingarg && r->count) { + el->el_state.doingarg = 1; + el->el_state.argument = r->count; + } + + el->el_chared.c_vcmd.pos = el->el_line.cursor; + el->el_chared.c_vcmd.action = r->action; + if (r->pos != r->buf) { + if (r->pos + 1 > r->lim) + /* sanity */ + r->pos = r->lim - 1; + r->pos[0] = 0; + el_push(el, r->buf); + } - return el->el_search.chadir == CHAR_BACK ? - cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : - cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); + el->el_state.thiscmd = r->cmd; + el->el_state.thisch = r->ch; + return (*el->el_map.func[r->cmd])(el, r->ch); } |