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