/* cv_action(): * Handle vi actions. */ static el_action_t cv_action(EditLine *el, wint_t c) { if (el->el_chared.c_vcmd.action != NOP) { /* 'cc', 'dd' and (possibly) friends */ if (c != (wint_t)el->el_chared.c_vcmd.action) return CC_ERROR; if (!(c & YANK)) cv_undo(el); cv_yank(el, el->el_line.buffer, (int)(el->el_line.lastchar - el->el_line.buffer)); el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = 0; if (!(c & YANK)) { el->el_line.lastchar = el->el_line.buffer; el->el_line.cursor = el->el_line.buffer; } if (c & INSERT) el->el_map.current = el->el_map.key; return CC_REFRESH; } el->el_chared.c_vcmd.pos = el->el_line.cursor; el->el_chared.c_vcmd.action = c; return CC_ARGHACK; }
/* cv_paste(): * Paste previous deletion before or after the cursor */ static el_action_t cv_paste(EditLine *el, wint_t c) { c_kill_t *k = &el->el_chared.c_kill; size_t len = (size_t)(k->last - k->buf); if (k->buf == NULL || len == 0) return CC_ERROR; #ifdef DEBUG_PASTE (void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len, k->buf); #endif cv_undo(el); if (!c && el->el_line.cursor < el->el_line.lastchar) el->el_line.cursor++; c_insert(el, (int)len); if (el->el_line.cursor + len > el->el_line.lastchar) return CC_ERROR; (void) memcpy(el->el_line.cursor, k->buf, len * sizeof(*el->el_line.cursor)); return CC_REFRESH; }
/* vi_change_case(): * Vi change case of character under the cursor and advance one character * [~] */ libedit_private el_action_t vi_change_case(EditLine *el, wint_t c) { int i; 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 = *el->el_line.cursor; if (iswupper(c)) *el->el_line.cursor = towlower(c); else if (iswlower(c)) *el->el_line.cursor = towupper(c); if (++el->el_line.cursor >= el->el_line.lastchar) { el->el_line.cursor--; re_fastaddc(el); break; } re_fastaddc(el); } return CC_NORM; }
/* vi_undo_line(): * Vi undo all changes to line * [U] */ libedit_private el_action_t /*ARGSUSED*/ vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) { cv_undo(el); return hist_get(el); }
/* vi_insert(): * Vi enter insert mode * [i] */ libedit_private el_action_t /*ARGSUSED*/ vi_insert(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_map.current = el->el_map.key; cv_undo(el); return CC_NORM; }
/* vi_add_at_eol(): * Vi enter insert mode at end of line * [A] */ libedit_private el_action_t /*ARGSUSED*/ vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_map.current = el->el_map.key; el->el_line.cursor = el->el_line.lastchar; cv_undo(el); return CC_CURSOR; }
/* vi_replace_mode(): * Vi enter replace mode * [R] */ libedit_private el_action_t /*ARGSUSED*/ vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_map.current = el->el_map.key; el->el_state.inputmode = MODE_REPLACE; cv_undo(el); return CC_NORM; }
/* vi_insert_at_bol(): * Vi enter insert mode at the beginning of line * [I] */ libedit_private el_action_t /*ARGSUSED*/ vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_line.cursor = el->el_line.buffer; cv_undo(el); el->el_map.current = el->el_map.key; return CC_CURSOR; }
/* vi_change_to_eol(): * Vi change to end of line * [C] */ libedit_private el_action_t /*ARGSUSED*/ vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) { cv_undo(el); cv_yank(el, el->el_line.cursor, (int)(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; }
/* vi_replace_char(): * Vi replace character under the cursor with the next character typed * [r] */ libedit_private el_action_t /*ARGSUSED*/ vi_replace_char(EditLine *el, wint_t 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; cv_undo(el); return CC_ARGHACK; }
/* 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_' */ libedit_private el_action_t /*ARGSUSED*/ vi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) { const wchar_t *wp = HIST_FIRST(el); const wchar_t *wep, *wsp; int len; wchar_t *cp; const wchar_t *lim; if (wp == NULL) return CC_ERROR; wep = wsp = NULL; do { while (iswspace(*wp)) wp++; if (*wp == 0) break; wsp = wp; while (*wp && !iswspace(*wp)) wp++; wep = wp; } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0); if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0)) return CC_ERROR; cv_undo(el); len = (int)(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_add(): * Vi enter insert mode after the cursor * [a] */ libedit_private el_action_t /*ARGSUSED*/ vi_add(EditLine *el, wint_t c __attribute__((__unused__))) { int ret; el->el_map.current = el->el_map.key; if (el->el_line.cursor < el->el_line.lastchar) { el->el_line.cursor++; if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; ret = CC_CURSOR; } else ret = CC_NORM; cv_undo(el); return (el_action_t)ret; }
/* c_delafter(): * Delete num characters after the cursor */ libedit_private void c_delafter(EditLine *el, int num) { if (el->el_line.cursor + num > el->el_line.lastchar) num = (int)(el->el_line.lastchar - el->el_line.cursor); if (el->el_map.current != el->el_map.emacs) { cv_undo(el); cv_yank(el, el->el_line.cursor, num); } if (num > 0) { wchar_t *cp; for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) *cp = cp[num]; el->el_line.lastchar -= num; } }