xref: /dragonfly/contrib/nvi2/ex/ex_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 
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  */
48 EXCMDLIST 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