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