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