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
22/*
23 * This array maps ex command names to command functions.
24 *
25 * The order in which command names are listed below is important --
26 * ambiguous abbreviations are resolved to be the first possible match,
27 * e.g. "r" means "read", not "rewind", because "read" is listed before
28 * "rewind".
29 *
30 * The syntax of the ex commands is unbelievably irregular, and a special
31 * case from beginning to end.  Each command has an associated "syntax
32 * script" which describes the "arguments" that are possible.  The script
33 * syntax is as follows:
34 *
35 *	!		-- ! flag
36 *	1		-- flags: [+-]*[pl#][+-]*
37 *	2		-- flags: [-.+^]
38 *	3		-- flags: [-.+^=]
39 *	b		-- buffer
40 *	c[01+a]		-- count (0-N, 1-N, signed 1-N, address offset)
41 *	f[N#][or]	-- file (a number or N, optional or required)
42 *	l		-- line
43 *	S		-- string with file name expansion
44 *	s		-- string
45 *	W		-- word string
46 *	w[N#][or]	-- word (a number or N, optional or required)
47 */
48EXCMDLIST const cmds[] = {
49/* C_SCROLL */
50	{L("\004"),	ex_pr,		E_ADDR2,
51	    "",
52	    "^D",
53	    "scroll lines"},
54/* C_BANG */
55	{L("!"),		ex_bang,	E_ADDR2_NONE|E_SECURE,
56	    "S",
57	    "[line [,line]] ! command",
58	    "filter lines through commands or run commands"},
59/* C_HASH */
60	{L("#"),		ex_number,	E_ADDR2|E_CLRFLAG,
61	    "ca1",
62	    "[line [,line]] # [count] [l]",
63	    "display numbered lines"},
64/* C_SUBAGAIN */
65	{L("&"),		ex_subagain,	E_ADDR2|E_ADDR_ZERO,
66	    "s",
67	    "[line [,line]] & [cgr] [count] [#lp]",
68	    "repeat the last subsitution"},
69/* C_STAR */
70	{L("*"),		ex_at,		0,
71	    "b",
72	    "* [buffer]",
73	    "execute a buffer"},
74/* C_SHIFTL */
75	{L("<"),		ex_shiftl,	E_ADDR2|E_AUTOPRINT,
76	    "ca1",
77	    "[line [,line]] <[<...] [count] [flags]",
78	    "shift lines left"},
79/* C_EQUAL */
80	{L("="),		ex_equal,	E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
81	    "1",
82	    "[line] = [flags]",
83	    "display line number"},
84/* C_SHIFTR */
85	{L(">"),		ex_shiftr,	E_ADDR2|E_AUTOPRINT,
86	    "ca1",
87	    "[line [,line]] >[>...] [count] [flags]",
88	    "shift lines right"},
89/* C_AT */
90	{L("@"),		ex_at,		E_ADDR2,
91	    "b",
92	    "@ [buffer]",
93	    "execute a buffer"},
94/* C_APPEND */
95	{L("append"),	ex_append,	E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
96	    "!",
97	    "[line] a[ppend][!]",
98	    "append input to a line"},
99/* C_ABBR */
100	{L("abbreviate"), 	ex_abbr,	0,
101	    "W",
102	    "ab[brev] [word replace]",
103	    "specify an input abbreviation"},
104/* C_ARGS */
105	{L("args"),	ex_args,	0,
106	    "",
107	    "ar[gs]",
108	    "display file argument list"},
109/* C_BG */
110	{L("bg"),		ex_bg,		E_VIONLY,
111	    "",
112	    "bg",
113	    "put a foreground screen into the background"},
114/* C_CHANGE */
115	{L("change"),	ex_change,	E_ADDR2|E_ADDR_ZERODEF,
116	    "!ca",
117	    "[line [,line]] c[hange][!] [count]",
118	    "change lines to input"},
119/* C_CD */
120	{L("cd"),		ex_cd,		0,
121	    "!f1o",
122	    "cd[!] [directory]",
123	    "change the current directory"},
124/* C_CHDIR */
125	{L("chdir"),	ex_cd,		0,
126	    "!f1o",
127	    "chd[ir][!] [directory]",
128	    "change the current directory"},
129/* C_COPY */
130	{L("copy"),	ex_copy,	E_ADDR2|E_AUTOPRINT,
131	    "l1",
132	    "[line [,line]] co[py] line [flags]",
133	    "copy lines elsewhere in the file"},
134/* C_CSCOPE */
135	{L("cscope"),      ex_cscope,      0,
136	    "!s",
137	    "cs[cope] command [args]",
138	    "create a set of tags using a cscope command"},
139/*
140 * !!!
141 * Adding new commands starting with 'd' may break the delete command code
142 * in ex_cmd() (the ex parser).  Read through the comments there, first.
143 */
144/* C_DELETE */
145	{L("delete"),	ex_delete,	E_ADDR2|E_AUTOPRINT,
146	    "bca1",
147	    "[line [,line]] d[elete][flags] [buffer] [count] [flags]",
148	    "delete lines from the file"},
149/* C_DISPLAY */
150	{L("display"),	ex_display,	0,
151	    "w1r",
152	    "display b[uffers] | c[onnections] | s[creens] | t[ags]",
153	    "display buffers, connections, screens or tags"},
154/* C_EDIT */
155	{L("edit"),	ex_edit,	E_NEWSCREEN,
156	    "f1o",
157	    "[Ee][dit][!] [+cmd] [file]",
158	    "begin editing another file"},
159/* C_EX */
160	{L("ex"),		ex_edit,	E_NEWSCREEN,
161	    "f1o",
162	    "[Ee]x[!] [+cmd] [file]",
163	    "begin editing another file"},
164/* C_EXUSAGE */
165	{L("exusage"),	ex_usage,	0,
166	    "w1o",
167	    "[exu]sage [command]",
168	    "display ex command usage statement"},
169/* C_FILE */
170	{L("file"),	ex_file,	0,
171	    "f1o",
172	    "f[ile] [name]",
173	    "display (and optionally set) file name"},
174/* C_FG */
175	{L("fg"),		ex_fg,		E_NEWSCREEN|E_VIONLY,
176	    "f1o",
177	    "[Ff]g [file]",
178	    "bring a backgrounded screen into the foreground"},
179/* C_GLOBAL */
180	{L("global"),	ex_global,	E_ADDR2_ALL,
181	    "!s",
182	    "[line [,line]] g[lobal][!] [;/]RE[;/] [commands]",
183	    "execute a global command on lines matching an RE"},
184/* C_HELP */
185	{L("help"),	ex_help,	0,
186	    "",
187	    "he[lp]",
188	    "display help statement"},
189/* C_INSERT */
190	{L("insert"),	ex_insert,	E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
191	    "!",
192	    "[line] i[nsert][!]",
193	    "insert input before a line"},
194/* C_JOIN */
195	{L("join"),	ex_join,	E_ADDR2|E_AUTOPRINT,
196	    "!ca1",
197	    "[line [,line]] j[oin][!] [count] [flags]",
198	    "join lines into a single line"},
199/* C_K */
200	{L("k"),		ex_mark,	E_ADDR1,
201	    "w1r",
202	    "[line] k key",
203	    "mark a line position"},
204/* C_LIST */
205	{L("list"),	ex_list,	E_ADDR2|E_CLRFLAG,
206	    "ca1",
207	    "[line [,line]] l[ist] [count] [#]",
208	    "display lines in an unambiguous form"},
209/* C_MOVE */
210	{L("move"),	ex_move,	E_ADDR2|E_AUTOPRINT,
211	    "l",
212	    "[line [,line]] m[ove] line",
213	    "move lines elsewhere in the file"},
214/* C_MARK */
215	{L("mark"),	ex_mark,	E_ADDR1,
216	    "w1r",
217	    "[line] ma[rk] key",
218	    "mark a line position"},
219/* C_MAP */
220	{L("map"),		ex_map,		0,
221	    "!W",
222	    "map[!] [keys replace]",
223	    "map input or commands to one or more keys"},
224/* C_MKEXRC */
225	{L("mkexrc"),	ex_mkexrc,	0,
226	    "!f1r",
227	    "mkexrc[!] file",
228	    "write a .exrc file"},
229/* C_NEXT */
230	{L("next"),	ex_next,	E_NEWSCREEN,
231	    "!fN",
232	    "[Nn][ext][!] [+cmd] [file ...]",
233	    "edit (and optionally specify) the next file"},
234/* C_NUMBER */
235	{L("number"),	ex_number,	E_ADDR2|E_CLRFLAG,
236	    "ca1",
237	    "[line [,line]] nu[mber] [count] [l]",
238	    "change display to number lines"},
239/* C_OPEN */
240	{L("open"),	ex_open,	E_ADDR1,
241	    "s",
242	    "[line] o[pen] [/RE/] [flags]",
243	    "enter \"open\" mode (not implemented)"},
244/* C_PRINT */
245	{L("print"),	ex_pr,		E_ADDR2|E_CLRFLAG,
246	    "ca1",
247	    "[line [,line]] p[rint] [count] [#l]",
248	    "display lines"},
249/* C_PRESERVE */
250	{L("preserve"),	ex_preserve,	0,
251	    "",
252	    "pre[serve]",
253	    "preserve an edit session for recovery"},
254/* C_PREVIOUS */
255	{L("previous"),	ex_prev,	E_NEWSCREEN,
256	    "!",
257	    "[Pp]rev[ious][!]",
258	    "edit the previous file in the file argument list"},
259/* C_PUT */
260	{L("put"),		ex_put,
261	    E_ADDR1|E_AUTOPRINT|E_ADDR_ZERO|E_ADDR_ZERODEF,
262	    "b",
263	    "[line] pu[t] [buffer]",
264	    "append a cut buffer to the line"},
265/* C_QUIT */
266	{L("quit"),	ex_quit,	0,
267	    "!",
268	    "q[uit][!]",
269	    "exit ex/vi"},
270/* C_READ */
271	{L("read"),	ex_read,	E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
272	    "s",
273	    "[line] r[ead] [!cmd | [file]]",
274	    "append input from a command or file to the line"},
275/* C_RECOVER */
276	{L("recover"),	ex_recover,	0,
277	    "!f1r",
278	    "recover[!] file",
279	    "recover a saved file"},
280/* C_RESIZE */
281	{L("resize"),	ex_resize,	E_VIONLY,
282	    "c+",
283	    "resize [+-]rows",
284	    "grow or shrink the current screen"},
285/* C_REWIND */
286	{L("rewind"),	ex_rew,		0,
287	    "!",
288	    "rew[ind][!]",
289	    "re-edit all the files in the file argument list"},
290/*
291 * !!!
292 * Adding new commands starting with 's' may break the substitute command code
293 * in ex_cmd() (the ex parser).  Read through the comments there, first.
294 */
295/* C_SUBSTITUTE */
296	{L("s"),		ex_s,		E_ADDR2|E_ADDR_ZERO,
297	    "s",
298	    "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]",
299	    "substitute on lines matching an RE"},
300/* C_SCRIPT */
301	{L("script"),	ex_script,	E_SECURE,
302	    "!f1o",
303	    "sc[ript][!] [file]",
304	    "run a shell in a screen"},
305/* C_SET */
306	{L("set"),		ex_set,		0,
307	    "wN",
308	    "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]",
309	    "set options (use \":set all\" to see all options)"},
310/* C_SHELL */
311	{L("shell"),	ex_shell,	E_SECURE,
312	    "",
313	    "sh[ell]",
314	    "suspend editing and run a shell"},
315/* C_SOURCE */
316	{L("source"),	ex_source,	0,
317	    "f1r",
318	    "so[urce] file",
319	    "read a file of ex commands"},
320/* C_STOP */
321	{L("stop"),	ex_stop,	E_SECURE,
322	    "!",
323	    "st[op][!]",
324	    "suspend the edit session"},
325/* C_SUSPEND */
326	{L("suspend"),	ex_stop,	E_SECURE,
327	    "!",
328	    "su[spend][!]",
329	    "suspend the edit session"},
330/* C_T */
331	{L("t"),		ex_copy,	E_ADDR2|E_AUTOPRINT,
332	    "l1",
333	    "[line [,line]] t line [flags]",
334	    "copy lines elsewhere in the file"},
335/* C_TAG */
336	{L("tag"),		ex_tag_push,	E_NEWSCREEN,
337	    "!w1o",
338	    "[Tt]a[g][!] [string]",
339	    "edit the file containing the tag"},
340/* C_TAGNEXT */
341	{L("tagnext"),	ex_tag_next,	0,
342	    "!",
343	    "tagn[ext][!]",
344	    "move to the next tag"},
345/* C_TAGPOP */
346	{L("tagpop"),	ex_tag_pop,	0,
347	    "!w1o",
348	    "tagp[op][!] [number | file]",
349	    "return to the previous group of tags"},
350/* C_TAGPREV */
351	{L("tagprev"),	ex_tag_prev,	0,
352	    "!",
353	    "tagpr[ev][!]",
354	    "move to the previous tag"},
355/* C_TAGTOP */
356	{L("tagtop"),	ex_tag_top,	0,
357	    "!",
358	    "tagt[op][!]",
359	    "discard all tags"},
360/* C_UNDO */
361	{L("undo"),	ex_undo,	E_AUTOPRINT,
362	    "",
363	    "u[ndo]",
364	    "undo the most recent change"},
365/* C_UNABBREVIATE */
366	{L("unabbreviate"),ex_unabbr,	0,
367	    "w1r",
368	    "una[bbrev] word",
369	    "delete an abbreviation"},
370/* C_UNMAP */
371	{L("unmap"),	ex_unmap,	0,
372	    "!w1r",
373	    "unm[ap][!] word",
374	    "delete an input or command map"},
375/* C_V */
376	{L("v"),		ex_v,		E_ADDR2_ALL,
377	    "s",
378	    "[line [,line]] v [;/]RE[;/] [commands]",
379	    "execute a global command on lines NOT matching an RE"},
380/* C_VERSION */
381	{L("version"),	ex_version,	0,
382	    "",
383	    "version",
384	    "display the program version information"},
385/* C_VISUAL_EX */
386	{L("visual"),	ex_visual,	E_ADDR1|E_ADDR_ZERODEF,
387	    "2c11",
388	    "[line] vi[sual] [-|.|+|^] [window_size] [flags]",
389	    "enter visual (vi) mode from ex mode"},
390/* C_VISUAL_VI */
391	{L("visual"),	ex_edit,	E_NEWSCREEN,
392	    "f1o",
393	    "[Vv]i[sual][!] [+cmd] [file]",
394	    "edit another file (from vi mode only)"},
395/* C_VIUSAGE */
396	{L("viusage"),	ex_viusage,	0,
397	    "w1o",
398	    "[viu]sage [key]",
399	    "display vi key usage statement"},
400/* C_VSPLIT */
401	{L("vsplit"),	ex_edit,	E_VIONLY,
402	    "f1o",
403	    "vs[plit] [+cmd] [file]",
404	    "split the current screen vertically"},
405/* C_WRITE */
406	{L("write"),	ex_write,	E_ADDR2_ALL|E_ADDR_ZERODEF,
407	    "!s",
408	    "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]",
409	    "write the file"},
410/* C_WN */
411	{L("wn"),		ex_wn,		E_ADDR2_ALL|E_ADDR_ZERODEF,
412	    "!s",
413	    "[line [,line]] wn[!] [>>] [file]",
414	    "write the file and switch to the next file"},
415/* C_WQ */
416	{L("wq"),		ex_wq,		E_ADDR2_ALL|E_ADDR_ZERODEF,
417	    "!s",
418	    "[line [,line]] wq[!] [>>] [file]",
419	    "write the file and exit"},
420/* C_XIT */
421	{L("xit"),		ex_xit,		E_ADDR2_ALL|E_ADDR_ZERODEF,
422	    "!f1o",
423	    "[line [,line]] x[it][!] [file]",
424	    "exit"},
425/* C_YANK */
426	{L("yank"),	ex_yank,	E_ADDR2,
427	    "bca",
428	    "[line [,line]] ya[nk] [buffer] [count]",
429	    "copy lines to a cut buffer"},
430/* C_Z */
431	{L("z"),		ex_z,		E_ADDR1,
432	    "3c01",
433	    "[line] z [-|.|+|^|=] [count] [flags]",
434	    "display different screens of the file"},
435/* C_SUBTILDE */
436	{L("~"),		ex_subtilde,	E_ADDR2|E_ADDR_ZERO,
437	    "s",
438	    "[line [,line]] ~ [cgr] [count] [#lp]",
439	    "replace previous RE with previous replacement string,"},
440	{NULL},
441};
442