xref: /minix/external/bsd/nvi/dist/vi/v_cmd.c (revision 0a6a1f1d)
1 /*	$NetBSD: v_cmd.c,v 1.3 2014/01/26 21:43:45 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 #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.3 2014/01/26 21:43:45 christos 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