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