📄 vi.c
字号:
/* $NetBSD: vi.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $ *//*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <config.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>/* * vi.c: Vi mode commands. */#include "el.h"private el_action_t cv_action(EditLine *, int);private el_action_t cv_paste(EditLine *, int);/* cv_action(): * Handle vi actions. */private el_action_tcv_action(EditLine *el, int c){ 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_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 */private el_action_tcv_paste(EditLine *el, int c){ char *ptr; 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: \"%.*s\"\n", len, k->buf);#endif 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, len); if (el->el_line.cursor + len > el->el_line.lastchar) return (CC_ERROR); (void) memcpy(ptr, k->buf, len +0u); return (CC_REFRESH);}/* vi_paste_next(): * Vi paste previous deletion to the right of the cursor * [p] */protected el_action_t/*ARGSUSED*/vi_paste_next(EditLine *el, int c __attribute__((__unused__))){ return (cv_paste(el, 0));}/* vi_paste_prev(): * Vi paste previous deletion to the left of the cursor * [P] */protected el_action_t/*ARGSUSED*/vi_paste_prev(EditLine *el, int c __attribute__((__unused__))){ return (cv_paste(el, 1));}/* vi_prev_big_word(): * Vi move to the previous space delimited word * [B] */protected el_action_t/*ARGSUSED*/vi_prev_big_word(EditLine *el, int c){ if (el->el_line.cursor == el->el_line.buffer) return (CC_ERROR); el->el_line.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, cv__isWord); if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } return (CC_CURSOR);}/* vi_prev_word(): * Vi move to the previous word * [b] */protected el_action_t/*ARGSUSED*/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_line.cursor, el->el_line.buffer, el->el_state.argument, cv__isword); if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } return (CC_CURSOR);}/* vi_next_big_word(): * Vi move to the next space delimited word * [W] */protected el_action_t/*ARGSUSED*/vi_next_big_word(EditLine *el, int c){ 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); if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } return (CC_CURSOR);}/* vi_next_word(): * Vi move to the next word * [w] */protected el_action_t/*ARGSUSED*/vi_next_word(EditLine *el, int c __attribute__((__unused__))){ 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); if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } return (CC_CURSOR);}/* vi_change_case(): * Vi change case of character under the cursor and advance one character * [~] */protected el_action_tvi_change_case(EditLine *el, int 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 = *(unsigned char *)el->el_line.cursor; if (isupper(c)) *el->el_line.cursor = tolower(c); else if (islower(c)) *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;}/* vi_change_meta(): * Vi change prefix command * [c] */protected el_action_t/*ARGSUSED*/vi_change_meta(EditLine *el, int c __attribute__((__unused__))){ /* * Delete with insert == change: first we delete and then we leave in * insert mode. */ return (cv_action(el, DELETE | INSERT));}/* vi_insert_at_bol(): * Vi enter insert mode at the beginning of line * [I] */protected el_action_t/*ARGSUSED*/vi_insert_at_bol(EditLine *el, int 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_replace_char(): * Vi replace character under the cursor with the next character typed * [r] */protected el_action_t/*ARGSUSED*/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; cv_undo(el); return (CC_ARGHACK);}/* vi_replace_mode(): * Vi enter replace mode * [R] */protected el_action_t/*ARGSUSED*/vi_replace_mode(EditLine *el, int c __attribute__((__unused__))){ el->el_map.current = el->el_map.key; el->el_state.inputmode = MODE_REPLACE; cv_undo(el); return (CC_NORM);}/* vi_substitute_char(): * Vi replace character under the cursor and enter insert mode * [s] */protected el_action_t/*ARGSUSED*/vi_substitute_char(EditLine *el, int c __attribute__((__unused__))){ c_delafter(el, el->el_state.argument); el->el_map.current = el->el_map.key; return (CC_REFRESH);}/* vi_substitute_line(): * Vi substitute entire line * [S] */protected el_action_t/*ARGSUSED*/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);}/* vi_change_to_eol(): * Vi change to end of line * [C] */protected el_action_t/*ARGSUSED*/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);}/* vi_insert(): * Vi enter insert mode * [i] */protected el_action_t/*ARGSUSED*/vi_insert(EditLine *el, int c __attribute__((__unused__))){ el->el_map.current = el->el_map.key; cv_undo(el); return (CC_NORM);}/* vi_add(): * Vi enter insert mode after the cursor * [a] */protected el_action_t/*ARGSUSED*/vi_add(EditLine *el, int 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 (ret);}/* vi_add_at_eol(): * Vi enter insert mode at end of line * [A] */protected el_action_t/*ARGSUSED*/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; cv_undo(el); return (CC_CURSOR);}/* vi_delete_meta(): * Vi delete prefix command * [d] */protected el_action_t/*ARGSUSED*/vi_delete_meta(EditLine *el, int c __attribute__((__unused__))){ return (cv_action(el, DELETE));}/* vi_end_big_word(): * Vi move to the end of the current space delimited word * [E] */protected el_action_t/*ARGSUSED*/vi_end_big_word(EditLine *el, int c){ 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, cv__isWord); if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); return (CC_REFRESH); } return (CC_CURSOR);}/* vi_end_word(): * Vi move to the end of the current word * [e] */protected el_action_t/*ARGSUSED*/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, cv__isword); if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); return (CC_REFRESH); } return (CC_CURSOR);}/* vi_undo(): * Vi undo last change * [u] */protected el_action_t/*ARGSUSED*/vi_undo(EditLine *el, int c __attribute__((__unused__))){ c_undo_t un = el->el_chared.c_undo; if (un.len == -1) 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);}/* vi_command_mode(): * Vi enter command mode (use alternative key bindings) * [<ESC>] */protected el_action_t/*ARGSUSED*/vi_command_mode(EditLine *el, int c __attribute__((__unused__))){ /* [Esc] cancels pending action */ el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = 0; el->el_state.doingarg = 0; el->el_state.inputmode = MODE_INSERT; el->el_map.current = el->el_map.alt;#ifdef VI_MOVE if (el->el_line.cursor > el->el_line.buffer) el->el_line.cursor--;#endif return (CC_CURSOR);}/* vi_zero(): * Vi move to the beginning of line * [0] */protected el_action_tvi_zero(EditLine *el, int c){ if (el->el_state.doingarg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -