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