Home | History | Annotate | Line # | Download | only in vi
      1 /*	$NetBSD: v_cmd.c,v 1.4 2017/10/22 06:26:01 pgoyette Exp $ */
      2 /*-
      3  * Copyright (c) 1992, 1993, 1994
      4  *	The Regents of the University of California.  All rights reserved.
      5  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      6  *	Keith Bostic.  All rights reserved.
      7  *
      8  * See the LICENSE file for redistribution information.
      9  */
     10 
     11 #include "config.h"
     12 
     13 #include <sys/cdefs.h>
     14 #if 0
     15 #ifndef lint
     16 static const char sccsid[] = "Id: v_cmd.c,v 10.9 1996/03/28 15:18:39 bostic Exp  (Berkeley) Date: 1996/03/28 15:18:39 ";
     17 #endif /* not lint */
     18 #else
     19 __RCSID("$NetBSD: v_cmd.c,v 1.4 2017/10/22 06:26:01 pgoyette Exp $");
     20 #endif
     21 
     22 #include <sys/types.h>
     23 #include <sys/queue.h>
     24 #include <sys/time.h>
     25 
     26 #include <bitstring.h>
     27 #include <limits.h>
     28 #include <stdio.h>
     29 
     30 #include "../common/common.h"
     31 #include "vi.h"
     32 
     33 #define VINULLKEY { NULL, 0, NULL, NULL }
     34 /*
     35  * This array maps keystrokes to vi command functions.  It is known
     36  * in ex/ex_usage.c that it takes four columns to name a vi character.
     37  */
     38 VIKEYS const vikeys [MAXVIKEY + 1] = {
     39 /* 000 NUL -- The code in vi.c expects key 0 to be undefined. */
     40 	VINULLKEY,
     41 /* 001  ^A */
     42 	{v_searchw,	V_ABS|V_CNT|V_MOVE|V_KEYW|VM_CUTREQ|VM_RCM_SET,
     43 	    "[count]^A",
     44 	    "^A search forward for cursor word"},
     45 /* 002  ^B */
     46 	{v_pageup,	V_CNT|VM_RCM_SET,
     47 	    "[count]^B",
     48 	    "^B scroll up by screens"},
     49 /* 003  ^C */
     50 	{NULL,		0,
     51 	    "^C",
     52 	    "^C interrupt an operation (e.g. read, write, search)"},
     53 /* 004  ^D */
     54 	{v_hpagedown,	V_CNT|VM_RCM_SET,
     55 	    "[count]^D",
     56 	    "^D scroll down by half screens (setting count)"},
     57 /* 005  ^E */
     58 	{v_linedown,	V_CNT,
     59 	    "[count]^E",
     60 	    "^E scroll down by lines"},
     61 /* 006  ^F */
     62 	{v_pagedown,	V_CNT|VM_RCM_SET,
     63 	    "[count]^F",
     64 	    "^F scroll down by screens"},
     65 /* 007  ^G */
     66 	{v_status,	0,
     67 	    "^G",
     68 	    "^G file status"},
     69 /* 010  ^H */
     70 	{v_left,	V_CNT|V_MOVE|VM_RCM_SET,
     71 	    "[count]^H",
     72 	    "^H move left by characters"},
     73 /* 011  ^I */
     74 	VINULLKEY,
     75 /* 012  ^J */
     76 	{v_down,	V_CNT|V_MOVE|VM_LMODE|VM_RCM,
     77 	    "[count]^J",
     78 	    "^J move down by lines"},
     79 /* 013  ^K */
     80 	VINULLKEY,
     81 /* 014  ^L */
     82 	{v_redraw,	0,
     83 	    "^L",
     84 	    "^L redraw screen"},
     85 /* 015  ^M */
     86 	{v_cr,		V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
     87 	    "[count]^M",
     88 	    "^M move down by lines (to first non-blank)"},
     89 /* 016  ^N */
     90 	{v_down,	V_CNT|V_MOVE|VM_LMODE|VM_RCM,
     91 	    "[count]^N",
     92 	    "^N move down by lines"},
     93 /* 017  ^O */
     94 	VINULLKEY,
     95 /* 020  ^P */
     96 	{v_up,		V_CNT|V_MOVE|VM_LMODE|VM_RCM,
     97 	    "[count]^P",
     98 	    "^P move up by lines"},
     99 /* 021  ^Q -- same as ^V if not used for hardware flow control. */
    100 	VINULLKEY,
    101 /* 022  ^R */
    102 	{v_redraw,	0,
    103 	    "^R",
    104 	    "^R redraw screen"},
    105 /* 023  ^S -- not available, used for hardware flow control. */
    106 	VINULLKEY,
    107 /* 024  ^T */
    108 	{v_tagpop,	V_ABS|VM_RCM_SET,
    109 	    "^T",
    110 	    "^T tag pop"},
    111 /* 025  ^U */
    112 	{v_hpageup,	V_CNT|VM_RCM_SET,
    113 	    "[count]^U",
    114 	    "^U half page up (set count)"},
    115 /* 026  ^V */
    116 	{NULL,		0,
    117 	    "^V",
    118 	    "^V input a literal character"},
    119 /* 027  ^W */
    120 	{v_screen,	0,
    121 	    "^W",
    122 	    "^W move to next screen"},
    123 /* 030  ^X */
    124 	VINULLKEY,
    125 /* 031  ^Y */
    126 	{v_lineup,	V_CNT,
    127 	    "[count]^Y",
    128 	    "^Y page up by lines"},
    129 /* 032  ^Z */
    130 	{v_suspend,	V_SECURE,
    131 	    "^Z",
    132 	    "^Z suspend editor"},
    133 /* 033  ^[ */
    134 	{NULL,		0,
    135 	    "^[ <escape>",
    136 	    "^[ <escape> exit input mode, cancel partial commands"},
    137 /* 034  ^\ */
    138 	{v_exmode,	0,
    139 	    "^\\",
    140 	    "^\\ switch to ex mode"},
    141 /* 035  ^] */
    142 	{v_tagpush,	V_ABS|V_KEYW|VM_RCM_SET,
    143 	    "^]",
    144 	    "^] tag push cursor word"},
    145 /* 036  ^^ */
    146 	{v_switch,	0,
    147 	    "^^",
    148 	    "^^ switch to previous file"},
    149 /* 037  ^_ */
    150 	VINULLKEY,
    151 /* 040 ' ' */
    152 	{v_right,	V_CNT|V_MOVE|VM_RCM_SET,
    153 	    "[count]' '",
    154 	    "   <space> move right by columns"},
    155 /* 041   ! */
    156 	{v_filter,	V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET,
    157 	    "[count]![count]motion command(s)",
    158 	    " ! filter through command(s) to motion"},
    159 /* 042   " */
    160 	VINULLKEY,
    161 /* 043   # */
    162 	{v_increment,	V_CHAR|V_CNT|V_DOT|VM_RCM_SET,
    163 	    "[count]# +|-|#",
    164 	    " # number increment/decrement"},
    165 /* 044   $ */
    166 	{v_dollar,	V_CNT|V_MOVE|VM_RCM_SETLAST,
    167 	    " [count]$",
    168 	    " $ move to last column"},
    169 /* 045   % */
    170 	{v_match,	V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    171 	    "%",
    172 	    " % move to match"},
    173 /* 046   & */
    174 	{v_again,	0,
    175 	    "&",
    176 	    " & repeat substitution"},
    177 /* 047   ' */
    178 	{v_fmark,	V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET,
    179 	    "'['a-z]",
    180 	    " ' move to mark (to first non-blank)"},
    181 /* 050   ( */
    182 	{v_sentenceb,	V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    183 	    "[count](",
    184 	    " ( move back sentence"},
    185 /* 051   ) */
    186 	{v_sentencef,	V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    187 	    "[count])",
    188 	    " ) move forward sentence"},
    189 /* 052   * */
    190 	VINULLKEY,
    191 /* 053   + */
    192 	{v_down,	V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
    193 	    "[count]+",
    194 	    " + move down by lines (to first non-blank)"},
    195 /* 054   , */
    196 	{v_chrrepeat,	V_CNT|V_MOVE|VM_RCM_SET,
    197 	    "[count],",
    198 	    " , reverse last F, f, T or t search"},
    199 /* 055   - */
    200 	{v_up,		V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
    201 	    "[count]-",
    202 	    " - move up by lines (to first non-blank)"},
    203 /* 056   . */
    204 	{NULL,		0,
    205 	    ".",
    206 	    " . repeat the last command"},
    207 /* 057   / */
    208 	{v_searchf,	V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    209 	    "/RE[/ offset]",
    210 	    " / search forward"},
    211 /* 060   0 */
    212 	{v_zero,	V_MOVE|VM_RCM_SET,
    213 	    "0",
    214 	    " 0 move to first character"},
    215 /* 061   1 */
    216 	VINULLKEY,
    217 /* 062   2 */
    218 	VINULLKEY,
    219 /* 063   3 */
    220 	VINULLKEY,
    221 /* 064   4 */
    222 	VINULLKEY,
    223 /* 065   5 */
    224 	VINULLKEY,
    225 /* 066   6 */
    226 	VINULLKEY,
    227 /* 067   7 */
    228 	VINULLKEY,
    229 /* 070   8 */
    230 	VINULLKEY,
    231 /* 071   9 */
    232 	VINULLKEY,
    233 /* 072   : */
    234 	{v_ex,		0,
    235 	    ":command [| command] ...",
    236 	    " : ex command"},
    237 /* 073   ; */
    238 	{v_chrepeat,	V_CNT|V_MOVE|VM_RCM_SET,
    239 	    "[count];",
    240 	    " ; repeat last F, f, T or t search"},
    241 /* 074   < */
    242 	{v_shiftl,	V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
    243 	    "[count]<[count]motion",
    244 	    " < shift lines left to motion"},
    245 /* 075   = */
    246 	VINULLKEY,
    247 /* 076   > */
    248 	{v_shiftr,	V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
    249 	    "[count]>[count]motion",
    250 	    " > shift lines right to motion"},
    251 /* 077   ? */
    252 	{v_searchb,	V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    253 	    "?RE[? offset]",
    254 	    " ? search backward"},
    255 /* 100   @ */
    256 	{v_at,		V_CNT|V_RBUF|VM_RCM_SET,
    257 	    "@buffer",
    258 	    " @ execute buffer"},
    259 /* 101   A */
    260 	{v_iA,		V_CNT|V_DOT|VM_RCM_SET,
    261 	    "[count]A",
    262 	    " A append to the line"},
    263 /* 102   B */
    264 	{v_wordB,	V_CNT|V_MOVE|VM_RCM_SET,
    265 	    "[count]B",
    266 	    " B move back bigword"},
    267 /* 103   C */
    268 	{NULL,		0,
    269 	    "[buffer][count]C",
    270 	    " C change to end-of-line"},
    271 /* 104   D */
    272 	{NULL,		0,
    273 	    "[buffer]D",
    274 	    " D delete to end-of-line"},
    275 /* 105   E */
    276 	{v_wordE,	V_CNT|V_MOVE|VM_RCM_SET,
    277 	    "[count]E",
    278 	    " E move to end of bigword"},
    279 /* 106   F */
    280 	{v_chF,		V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
    281 	    "[count]F character",
    282 	    " F character in line backward search"},
    283 /* 107   G */
    284 	{v_lgoto,	V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
    285 	    "[count]G",
    286 	    " G move to line"},
    287 /* 110   H */
    288 	{v_home,	V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
    289 	    "[count]H",
    290 	    " H move to count lines from screen top"},
    291 /* 111   I */
    292 	{v_iI,		V_CNT|V_DOT|VM_RCM_SET,
    293 	    "[count]I",
    294 	    " I insert before first nonblank"},
    295 /* 112   J */
    296 	{v_join,	V_CNT|V_DOT|VM_RCM_SET,
    297 	    "[count]J",
    298 	    " J join lines"},
    299 /* 113   K */
    300 	VINULLKEY,
    301 /* 114   L */
    302 	{v_bottom,	V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
    303 	    "[count]L",
    304 	    " L move to screen bottom"},
    305 /* 115   M */
    306 	{v_middle,	V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
    307 	    "M",
    308 	    " M move to screen middle"},
    309 /* 116   N */
    310 	{v_searchN,	V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    311 	    "n",
    312 	    " N reverse last search"},
    313 /* 117   O */
    314 	{v_iO,		V_CNT|V_DOT|VM_RCM_SET,
    315 	    "[count]O",
    316 	    " O insert above line"},
    317 /* 120   P */
    318 	{v_Put,		V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
    319 	    "[buffer]P",
    320 	    " P insert before cursor from buffer"},
    321 /* 121   Q */
    322 	{v_exmode,	0,
    323 	    "Q",
    324 	    " Q switch to ex mode"},
    325 /* 122   R */
    326 	{v_Replace,	V_CNT|V_DOT|VM_RCM_SET,
    327 	    "[count]R",
    328 	    " R replace characters"},
    329 /* 123   S */
    330 	{NULL,		0,
    331 	    "[buffer][count]S",
    332 	    " S substitute for the line(s)"},
    333 /* 124   T */
    334 	{v_chT,		V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
    335 	    "[count]T character",
    336 	    " T before character in line backward search"},
    337 /* 125   U */
    338 	{v_Undo,	VM_RCM_SET,
    339 	    "U",
    340 	    " U Restore the current line"},
    341 /* 126   V */
    342 	VINULLKEY,
    343 /* 127   W */
    344 	{v_wordW,	V_CNT|V_MOVE|VM_RCM_SET,
    345 	    "[count]W",
    346 	    " W move to next bigword"},
    347 /* 130   X */
    348 	{v_Xchar,	V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
    349 	    "[buffer][count]X",
    350 	    " X delete character before cursor"},
    351 /* 131   Y */
    352 	{NULL,		0,
    353 	    "[buffer][count]Y",
    354 	    " Y copy line"},
    355 /* 132   Z */
    356 	{v_zexit,	0,
    357 	    "ZZ",
    358 	    "ZZ save file and exit"},
    359 /* 133   [ */
    360 	{v_sectionb,	V_ABS|V_CNT|V_MOVE|VM_RCM_SET,
    361 	    "[[",
    362 	    "[[ move back section"},
    363 /* 134   \ */
    364 	VINULLKEY,
    365 /* 135   ] */
    366 	{v_sectionf,	V_ABS|V_CNT|V_MOVE|VM_RCM_SET,
    367 	    "]]",
    368 	    "]] move forward section"},
    369 /* 136   ^ */
    370 	/*
    371 	 * DON'T set the VM_RCM_SETFNB flag, the function has to do the work
    372 	 * anyway, in case it's a motion component.  DO set VM_RCM_SET, so
    373 	 * that any motion that's part of a command is preserved.
    374 	 */
    375 	{v_first,	V_CNT|V_MOVE|VM_RCM_SET,
    376 	    "^",
    377 	    " ^ move to first non-blank"},
    378 /* 137   _ */
    379 	/*
    380 	 * Needs both to set the VM_RCM_SETFNB flag, and to do the work
    381 	 * in the function, in case it's a delete.
    382 	 */
    383 	{v_cfirst,	V_CNT|V_MOVE|VM_RCM_SETFNB,
    384 	    "_",
    385 	    " _ move to first non-blank"},
    386 /* 140   ` */
    387 	{v_bmark,	V_ABS_C|V_CHAR|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    388 	    "`[`a-z]",
    389 	    " ` move to mark"},
    390 /* 141   a */
    391 	{v_ia,		V_CNT|V_DOT|VM_RCM_SET,
    392 	    "[count]a",
    393 	    " a append after cursor"},
    394 /* 142   b */
    395 	{v_wordb,	V_CNT|V_MOVE|VM_RCM_SET,
    396 	    "[count]b",
    397 	    " b move back word"},
    398 /* 143   c */
    399 	{v_change,	V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
    400 	    "[buffer][count]c[count]motion",
    401 	    " c change to motion"},
    402 /* 144   d */
    403 	{v_delete,	V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
    404 	    "[buffer][count]d[count]motion",
    405 	    " d delete to motion"},
    406 /* 145   e */
    407 	{v_worde,	V_CNT|V_MOVE|VM_RCM_SET,
    408 	    "[count]e",
    409 	    " e move to end of word"},
    410 /* 146   f */
    411 	{v_chf,		V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
    412 	    "[count]f character",
    413 	    " f character in line forward search"},
    414 /* 147   g */
    415 	VINULLKEY,
    416 /* 150   h */
    417 	{v_left,	V_CNT|V_MOVE|VM_RCM_SET,
    418 	    "[count]h",
    419 	    " h move left by columns"},
    420 /* 151   i */
    421 	{v_ii,		V_CNT|V_DOT|VM_RCM_SET,
    422 	    "[count]i",
    423 	    " i insert before cursor"},
    424 /* 152   j */
    425 	{v_down,	V_CNT|V_MOVE|VM_LMODE|VM_RCM,
    426 	    "[count]j",
    427 	    " j move down by lines"},
    428 /* 153   k */
    429 	{v_up,		V_CNT|V_MOVE|VM_LMODE|VM_RCM,
    430 	    "[count]k",
    431 	    " k move up by lines"},
    432 /* 154   l */
    433 	{v_right,	V_CNT|V_MOVE|VM_RCM_SET,
    434 	    "[count]l",
    435 	    " l move right by columns"},
    436 /* 155   m */
    437 	{v_mark,	V_CHAR,
    438 	    "m[a-z]",
    439 	    " m set mark"},
    440 /* 156   n */
    441 	{v_searchn,	V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    442 	    "n",
    443 	    " n repeat last search"},
    444 /* 157   o */
    445 	{v_io,		V_CNT|V_DOT|VM_RCM_SET,
    446 	    "[count]o",
    447 	    " o append after line"},
    448 /* 160   p */
    449 	{v_put,		V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
    450 	    "[buffer]p",
    451 	    " p insert after cursor from buffer"},
    452 /* 161   q */
    453 	VINULLKEY,
    454 /* 162   r */
    455 	{v_replace,	V_CNT|V_DOT|VM_RCM_SET,
    456 	    "[count]r character",
    457 	    " r replace character"},
    458 /* 163   s */
    459 	{v_subst,	V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
    460 	    "[buffer][count]s",
    461 	    " s substitute character"},
    462 /* 164   t */
    463 	{v_cht,		V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
    464 	    "[count]t character",
    465 	    " t before character in line forward search"},
    466 /* 165   u */
    467 	/*
    468 	 * DON'T set the V_DOT flag, it' more complicated than that.
    469 	 * See vi/vi.c for details.
    470 	 */
    471 	{v_undo,	VM_RCM_SET,
    472 	    "u",
    473 	    " u undo last change"},
    474 /* 166   v */
    475 	VINULLKEY,
    476 /* 167   w */
    477 	{v_wordw,	V_CNT|V_MOVE|VM_RCM_SET,
    478 	    "[count]w",
    479 	    " w move to next word"},
    480 /* 170   x */
    481 	{v_xchar,	V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
    482 	    "[buffer][count]x",
    483 	    " x delete character"},
    484 /* 171   y */
    485 	{v_yank,	V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
    486 	    "[buffer][count]y[count]motion",
    487 	    " y copy text to motion into a cut buffer"},
    488 /* 172   z */
    489 	/*
    490 	 * DON'T set the V_CHAR flag, the char isn't required,
    491 	 * so it's handled specially in getcmd().
    492 	 */
    493 	{v_z, 		V_ABS_L|V_CNT|VM_RCM_SETFNB,
    494 	    "[line]z[window_size][-|.|+|^|<CR>]",
    495 	    " z reposition the screen"},
    496 /* 173   { */
    497 	{v_paragraphb,	V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    498 	    "[count]{",
    499 	    " { move back paragraph"},
    500 /* 174   | */
    501 	{v_ncol,	V_CNT|V_MOVE|VM_RCM_SET,
    502 	    "[count]|",
    503 	    " | move to column"},
    504 /* 175   } */
    505 	{v_paragraphf,	V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
    506 	    "[count]}",
    507 	    " } move forward paragraph"},
    508 /* 176   ~ */
    509 	{v_ulcase,	V_CNT|V_DOT|VM_RCM_SET,
    510 	    "[count]~",
    511 	    " ~ reverse case"},
    512 };
    513