📄 vi.c
字号:
/* vi.c *//* Author: * Steve Kirkendall * Beaverton, OR 97005 * kirkenda@cs.pdx.edu */#include "config.h"#include "ctype.h"#include "vi.h"/* This array describes what each key does */#define NO_FUNC (MARK (*)())0#define NO_ARGS 0#define CURSOR 1#define CURSOR_CNT_KEY 2#define CURSOR_MOVED 3#define CURSOR_EOL 4#define ZERO 5#define DIGIT 6#define CURSOR_TEXT 7#define KEYWORD 8#define ARGSMASK 0x0f#define C_C_K_REP1 (CURSOR_CNT_KEY | 0x10)#define C_C_K_CUT (CURSOR_CNT_KEY | 0x20)#define C_C_K_MARK (CURSOR_CNT_KEY | 0x30)#define C_C_K_CHAR (CURSOR_CNT_KEY | 0x40)#ifndef NO_SHOWMODEstatic int keymodes[] = {0, WHEN_REP1, WHEN_CUT, WHEN_MARK, WHEN_CHAR};# define KEYMODE(args) (keymodes[(args) >> 4])#else# define KEYMODE(args) 0#endifstatic struct keystru{ MARK (*func)(); /* the function to run */ uchar args; /* description of the args needed */#ifndef NO_VISIBLE short flags;#else uchar flags; /* other stuff */#endif} vikeys[] ={/* NUL not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#ifndef NO_EXTENSIONS/* ^A find cursor word */ {m_wsrch, KEYWORD, MVMT|NREL|VIZ},#else/* ^A not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* ^B page backward */ {m_scroll, CURSOR, FRNT|VIZ},/* ^C not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^D scroll dn 1/2page*/ {m_scroll, CURSOR, NCOL|VIZ},/* ^E scroll up */ {m_scroll, CURSOR, NCOL|VIZ},/* ^F page forward */ {m_scroll, CURSOR, FRNT|VIZ},/* ^G show file status */ {v_status, NO_ARGS, NO_FLAGS},/* ^H move left, like h*/ {m_left, CURSOR, MVMT|VIZ},/* ^I not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^J move down */ {m_updnto, CURSOR, MVMT|LNMD|VIZ|INCL},/* ^K not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^L redraw screen */ {v_redraw, NO_ARGS, NO_FLAGS|VIZ},/* ^M mv front next ln */ {m_updnto, CURSOR, MVMT|FRNT|LNMD|VIZ|INCL},/* ^N move down */ {m_updnto, CURSOR, MVMT|LNMD|VIZ|INCL|NCOL},/* ^O not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^P move up */ {m_updnto, CURSOR, MVMT|LNMD|VIZ|INCL|NCOL},/* ^Q not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^R redraw screen */ {v_redraw, NO_ARGS, NO_FLAGS|VIZ},/* ^S not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^T not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^U scroll up 1/2page*/ {m_scroll, CURSOR, NCOL|VIZ},/* ^V not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^W not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^X move to phys col */ {m_tocol, CURSOR, MVMT|NREL|VIZ},/* ^Y scroll down */ {m_scroll, CURSOR, NCOL|VIZ},#ifdef SIGTSTP/* ^Z suspend elvis */ {v_suspend, NO_ARGS, NO_FLAGS},#else/* ^Z not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* ESC not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^\ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ^] keyword is tag */ {v_tag, KEYWORD, NO_FLAGS},/* ^^ previous file */ {v_switch, CURSOR, NO_FLAGS},/* ^_ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* SPC move right,like l*/ {m_right, CURSOR, MVMT|INCL|VIZ},/* ! run thru filter */ {v_filter, CURSOR_MOVED, FRNT|LNMD|INCL|VIZ},/* " select cut buffer*/ {v_selcut, C_C_K_CUT, PTMV|VIZ},#ifndef NO_EXTENSIONS/* # increment number */ {v_increment, KEYWORD, SDOT},#else/* # not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* $ move to rear */ {m_rear, CURSOR, MVMT|INCL|VIZ},/* % move to match */ {m_match, CURSOR, MVMT|INCL|VIZ},/* & repeat subst */ {v_again, CURSOR_MOVED, SDOT|NCOL|LNMD|INCL},/* ' move to a mark */ {m_tomark, C_C_K_MARK, MVMT|FRNT|NREL|LNMD|INCL|VIZ},#ifndef NO_SENTENCE/* ( mv back sentence */ {m_sentence, CURSOR, MVMT|VIZ},/* ) mv fwd sentence */ {m_sentence, CURSOR, MVMT|VIZ},#else/* ( not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* ) not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif#ifndef NO_ERRLIST/* * errlist */ {v_errlist, CURSOR, FRNT|NREL},#else/* * not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* + mv front next ln */ {m_updnto, CURSOR, MVMT|FRNT|LNMD|VIZ|INCL},#ifndef NO_CHARSEARCH/* , reverse [fFtT] cmd*/ {m__ch, CURSOR, MVMT|INCL|VIZ},#else/* , not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* - mv front prev ln */ {m_updnto, CURSOR, MVMT|FRNT|LNMD|VIZ|INCL},/* . special... */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* / forward search */ {m_fsrch, CURSOR_TEXT, MVMT|NREL|VIZ},/* 0 part of count? */ {NO_FUNC, ZERO, MVMT|PTMV|VIZ},/* 1 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 2 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 3 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 4 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 5 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 6 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 7 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 8 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* 9 part of count */ {NO_FUNC, DIGIT, PTMV|VIZ},/* : run single EX cmd*/ {v_1ex, CURSOR_TEXT, NO_FLAGS},#ifndef NO_CHARSEARCH/* ; repeat [fFtT] cmd*/ {m__ch, CURSOR, MVMT|INCL|VIZ},#else/* ; not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS|VIZ},#endif/* < shift text left */ {v_lshift, CURSOR_MOVED, SDOT|FRNT|LNMD|INCL|VIZ},/* = preset filter */ {v_reformat, CURSOR_MOVED, SDOT|FRNT|LNMD|INCL|VIZ},/* > shift text right */ {v_rshift, CURSOR_MOVED, SDOT|FRNT|LNMD|INCL|VIZ},/* ? backward search */ {m_bsrch, CURSOR_TEXT, MVMT|NREL|VIZ},#ifndef NO_AT/* @ execute a cutbuf */ {v_at, C_C_K_CUT, NO_FLAGS},#else/* @ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* A append at EOL */ {v_insert, CURSOR, SDOT},/* B move back Word */ {m_bword, CURSOR, MVMT|VIZ},/* C change to EOL */ {v_change, CURSOR_EOL, SDOT},/* D delete to EOL */ {v_delete, CURSOR_EOL, SDOT},/* E move end of Word */ {m_eword, CURSOR, MVMT|INCL|VIZ},#ifndef NO_CHARSEARCH/* F move bk to char */ {m_Fch, C_C_K_CHAR, MVMT|INCL|VIZ},#else/* F not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* G move to line # */ {m_updnto, CURSOR, MVMT|NREL|LNMD|FRNT|INCL|VIZ},/* H move to row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},/* I insert at front */ {v_insert, CURSOR, SDOT},/* J join lines */ {v_join, CURSOR, SDOT},#ifndef NO_EXTENSIONS/* K look up keyword */ {v_keyword, KEYWORD, NO_FLAGS},#else/* K not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* L move to last row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},/* M move to mid row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},/* N reverse prev srch*/ {m_Nsrch, CURSOR, MVMT|NREL|VIZ},/* O insert above line*/ {v_insert, CURSOR, SDOT},/* P paste before */ {v_paste, CURSOR, SDOT},/* Q quit to EX mode */ {v_quit, NO_ARGS, NO_FLAGS},/* R overtype */ {v_overtype, CURSOR, SDOT},/* S change line */ {v_change, CURSOR_MOVED, SDOT},#ifndef NO_CHARSEARCH/* T move bk to char */ {m_Tch, C_C_K_CHAR, MVMT|INCL|VIZ},#else/* T not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* U undo whole line */ {v_undoline, CURSOR, FRNT},#ifndef NO_VISIBLE/* V start visible */ {v_start, CURSOR, INCL|LNMD|VIZ},#else/* V not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* W move forward Word*/ {m_fword, CURSOR, MVMT|INCL|VIZ},/* X delete to left */ {v_xchar, CURSOR, SDOT},/* Y yank text */ {v_yank, CURSOR_MOVED, NCOL},/* Z save file & exit */ {v_xit, CURSOR_CNT_KEY, NO_FLAGS},/* [ move back section*/ {m_paragraph, CURSOR, MVMT|LNMD|NREL|VIZ},#ifndef NO_POPUP/* \ pop-up menu */ {v_popup, CURSOR_MOVED, VIZ},#else/* \ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* ] move fwd section */ {m_paragraph, CURSOR, MVMT|LNMD|NREL|VIZ},/* ^ move to front */ {m_front, CURSOR, MVMT|VIZ},/* _ current line */ {m_updnto, CURSOR, MVMT|LNMD|FRNT|INCL},/* ` move to mark */ {m_tomark, C_C_K_MARK, MVMT|NREL|VIZ},/* a append at cursor */ {v_insert, CURSOR, SDOT},/* b move back word */ {m_bword, CURSOR, MVMT|VIZ},/* c change text */ {v_change, CURSOR_MOVED, SDOT|VIZ},/* d delete op */ {v_delete, CURSOR_MOVED, SDOT|VIZ},/* e move end word */ {m_eword, CURSOR, MVMT|INCL|VIZ},#ifndef NO_CHARSEARCH/* f move fwd for char*/ {m_fch, C_C_K_CHAR, MVMT|INCL|VIZ},#else/* f not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* g not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* h move left */ {m_left, CURSOR, MVMT|VIZ},/* i insert at cursor */ {v_insert, CURSOR, SDOT},/* j move down */ {m_updnto, CURSOR, MVMT|NCOL|LNMD|VIZ|INCL},/* k move up */ {m_updnto, CURSOR, MVMT|NCOL|LNMD|VIZ|INCL},/* l move right */ {m_right, CURSOR, MVMT|INCL|VIZ},/* m define a mark */ {v_mark, C_C_K_MARK, NO_FLAGS},/* n repeat prev srch */ {m_nsrch, CURSOR, MVMT|NREL|VIZ},/* o insert below line*/ {v_insert, CURSOR, SDOT},/* p paste after */ {v_paste, CURSOR, SDOT},/* q not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},/* r replace chars */ {v_replace, C_C_K_REP1, SDOT},/* s subst N chars */ {v_subst, CURSOR, SDOT},#ifndef NO_CHARSEARCH/* t move fwd to char */ {m_tch, C_C_K_CHAR, MVMT|INCL|VIZ},#else/* t not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* u undo */ {v_undo, CURSOR, NO_FLAGS},#ifndef NO_VISIBLE/* v start visible */ {v_start, CURSOR, INCL|VIZ},#else/* v not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},#endif/* w move fwd word */ {m_fword, CURSOR, MVMT|INCL|VIZ},/* x delete character */ {v_xchar, CURSOR, SDOT},/* y yank text */ {v_yank, CURSOR_MOVED, NCOL|VIZ},/* z adjust scrn row */ {m_z, CURSOR_CNT_KEY, NCOL|VIZ},/* { back paragraph */ {m_paragraph, CURSOR, MVMT|LNMD|VIZ},/* | move to column */ {m_tocol, CURSOR, MVMT|NREL|VIZ},/* } fwd paragraph */ {m_paragraph, CURSOR, MVMT|LNMD|VIZ},/* ~ upper/lowercase */ {v_ulcase, CURSOR, SDOT},/* DEL not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS}};void vi(){ REG int key; /* keystroke from user */ long count; /* numeric argument to some functions */ REG struct keystru *keyptr;/* pointer to vikeys[] element */ MARK tcurs; /* temporary cursor */ int prevkey;/* previous key, if d/c/y/</>/! */ MARK range; /* start of range for d/c/y/</>/! */ char text[132]; int dotkey; /* last "key" of a change */ int dotpkey;/* last "prevkey" of a change */ int dotkey2;/* last extra "getkey()" of a change */ int dotcnt; /* last "count" of a change */ int firstkey; REG int i; /* tell the redraw() function to start from scratch */ redraw(MARK_UNSET, FALSE);#ifdef lint /* lint says that "range" might be used before it is set. This * can't really happen due to the way "range" and "prevkey" are used, * but lint doesn't know that. This line is here ONLY to keep lint * happy. */ range = 0L;#endif /* safeguard against '.' with no previous command */ dotkey = dotpkey = dotkey2 = dotcnt = 0; /* go immediately into insert mode, if ":set inputmode" */ firstkey = 0;#ifndef NO_EXTENSIONS if (*o_inputmode) { firstkey = 'i'; }#endif /* Repeatedly handle VI commands */ for (count = 0, prevkey = '\0'; mode == MODE_VI; ) { /* if we've moved off the undoable line, then we can't undo it at all */ if (markline(cursor) != U_line) { U_line = 0L; } /* report any changes from the previous command */ if (rptlines >= *o_report) { redraw(cursor, FALSE); msg("%ld line%s %s", rptlines, (rptlines==1?"":"s"), rptlabel); } rptlines = 0L; /* get the next command key. It must be ASCII */ if (firstkey) { key = firstkey; firstkey = 0; } else { do { key = getkey(WHEN_VICMD); } while (key < 0 || key > 127); } /* Convert a doubled-up operator such as "dd" into "d_" */ if (prevkey && key == prevkey) { key = '_'; } /* look up the structure describing this command */ keyptr = &vikeys[key]; /* '&' and uppercase operators always act like doubled */ if (!prevkey && keyptr->args == CURSOR_MOVED && (key == '&' || isupper(key))) { range = cursor; prevkey = key; key = '_'; keyptr = &vikeys[key]; }#ifndef NO_VISIBLE /* if we're in the middle of a v/V command, reject commands * that aren't operators or movement commands */ if (V_from && !(keyptr->flags & VIZ)) { beep(); prevkey = 0; count = 0; continue; }#endif /* if we're in the middle of a d/c/y/</>/! command, reject * anything but movement. */ if (prevkey && !(keyptr->flags & (MVMT|PTMV))) { beep(); prevkey = 0; count = 0; continue; } /* set the "dot" variables, if we're supposed to */ if (((keyptr->flags & SDOT) || (prevkey && vikeys[prevkey].flags & SDOT))#ifndef NO_VISIBLE && !V_from#endif ) { dotkey = key; dotpkey = prevkey; dotkey2 = '\0'; dotcnt = count; /* remember the line before any changes are made */ if (U_line != markline(cursor)) { U_line = markline(cursor); strcpy(U_text, fetchline(U_line)); } } /* if this is "." then set other vars from the "dot" vars */ if (key == '.') { key = dotkey; keyptr = &vikeys[key]; prevkey = dotpkey; if (prevkey) { range = cursor; } if (count == 0) { count = dotcnt; } doingdot = TRUE; /* remember the line before any changes are made */ if (U_line != markline(cursor)) { U_line = markline(cursor); strcpy(U_text, fetchline(U_line)); } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -