common/log.c: minor whitespace change
[nvi.git] / ex / ex_cmd.c
blob46cd5497a377b4d22e28e1288e98fd89f7b44b2d
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.
7 * See the LICENSE file for redistribution information.
8 */
10 #include "config.h"
12 #ifndef lint
13 static const char sccsid[] = "$Id: ex_cmd.c,v 10.25 2001/06/10 10:23:44 skimo Exp $ (Berkeley) $Date: 2001/06/10 10:23:44 $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
19 #include <bitstring.h>
20 #include <limits.h>
21 #include <stdio.h>
23 #include "../common/common.h"
26 * This array maps ex command names to command functions.
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".
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:
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)
51 EXCMDLIST const cmds[] = {
52 /* C_SCROLL */
53 {L("\004"), ex_pr, E_ADDR2,
54 "",
55 "^D",
56 "scroll lines"},
57 /* C_BANG */
58 {L("!"), 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 {L("#"), ex_number, E_ADDR2|E_CLRFLAG,
64 "ca1",
65 "[line [,line]] # [count] [l]",
66 "display numbered lines"},
67 /* C_SUBAGAIN */
68 {L("&"), ex_subagain, E_ADDR2|E_ADDR_ZERO,
69 "s",
70 "[line [,line]] & [cgr] [count] [#lp]",
71 "repeat the last subsitution"},
72 /* C_STAR */
73 {L("*"), ex_at, 0,
74 "b",
75 "* [buffer]",
76 "execute a buffer"},
77 /* C_SHIFTL */
78 {L("<"), ex_shiftl, E_ADDR2|E_AUTOPRINT,
79 "ca1",
80 "[line [,line]] <[<...] [count] [flags]",
81 "shift lines left"},
82 /* C_EQUAL */
83 {L("="), ex_equal, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
84 "1",
85 "[line] = [flags]",
86 "display line number"},
87 /* C_SHIFTR */
88 {L(">"), ex_shiftr, E_ADDR2|E_AUTOPRINT,
89 "ca1",
90 "[line [,line]] >[>...] [count] [flags]",
91 "shift lines right"},
92 /* C_AT */
93 {L("@"), ex_at, E_ADDR2,
94 "b",
95 "@ [buffer]",
96 "execute a buffer"},
97 /* C_APPEND */
98 {L("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 {L("abbreviate"), ex_abbr, 0,
104 "W",
105 "ab[brev] [word replace]",
106 "specify an input abbreviation"},
107 /* C_ARGS */
108 {L("args"), ex_args, 0,
110 "ar[gs]",
111 "display file argument list"},
112 /* C_BG */
113 {L("bg"), ex_bg, E_VIONLY,
115 "bg",
116 "put a foreground screen into the background"},
117 /* C_CHANGE */
118 {L("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 {L("cd"), ex_cd, 0,
124 "!f1o",
125 "cd[!] [directory]",
126 "change the current directory"},
127 /* C_CHDIR */
128 {L("chdir"), ex_cd, 0,
129 "!f1o",
130 "chd[ir][!] [directory]",
131 "change the current directory"},
132 /* C_COPY */
133 {L("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 {L("cscope"), ex_cscope, 0,
139 "!s",
140 "cs[cope] command [args]",
141 "create a set of tags using a cscope command"},
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.
147 /* C_DELETE */
148 {L("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 {L("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 {L("edit"), ex_edit, E_NEWSCREEN,
159 "f1o",
160 "[Ee][dit][!] [+cmd] [file]",
161 "begin editing another file"},
162 /* C_EX */
163 {L("ex"), ex_edit, E_NEWSCREEN,
164 "f1o",
165 "[Ee]x[!] [+cmd] [file]",
166 "begin editing another file"},
167 /* C_EXUSAGE */
168 {L("exusage"), ex_usage, 0,
169 "w1o",
170 "[exu]sage [command]",
171 "display ex command usage statement"},
172 /* C_FILE */
173 {L("file"), ex_file, 0,
174 "f1o",
175 "f[ile] [name]",
176 "display (and optionally set) file name"},
177 /* C_FG */
178 {L("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 {L("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 {L("help"), ex_help, 0,
190 "he[lp]",
191 "display help statement"},
192 /* C_INSERT */
193 {L("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 {L("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 {L("k"), ex_mark, E_ADDR1,
204 "w1r",
205 "[line] k key",
206 "mark a line position"},
207 /* C_LIST */
208 {L("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 {L("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 {L("mark"), ex_mark, E_ADDR1,
219 "w1r",
220 "[line] ma[rk] key",
221 "mark a line position"},
222 /* C_MAP */
223 {L("map"), ex_map, 0,
224 "!W",
225 "map[!] [keys replace]",
226 "map input or commands to one or more keys"},
227 /* C_MKEXRC */
228 {L("mkexrc"), ex_mkexrc, 0,
229 "!f1r",
230 "mkexrc[!] file",
231 "write a .exrc file"},
232 /* C_NEXT */
233 {L("next"), ex_next, E_NEWSCREEN,
234 "!fN",
235 "[Nn][ext][!] [+cmd] [file ...]",
236 "edit (and optionally specify) the next file"},
237 /* C_NUMBER */
238 {L("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 {L("open"), ex_open, E_ADDR1,
244 "s",
245 "[line] o[pen] [/RE/] [flags]",
246 "enter \"open\" mode (not implemented)"},
247 /* C_PRINT */
248 {L("print"), ex_pr, E_ADDR2|E_CLRFLAG,
249 "ca1",
250 "[line [,line]] p[rint] [count] [#l]",
251 "display lines"},
252 /* C_PERLCMD */
253 {L("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 {L("perldo"), ex_perl, E_ADDR2|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 {L("preserve"), ex_preserve, 0,
267 "pre[serve]",
268 "preserve an edit session for recovery"},
269 /* C_PREVIOUS */
270 {L("previous"), ex_prev, E_NEWSCREEN,
271 "!",
272 "[Pp]rev[ious][!]",
273 "edit the previous file in the file argument list"},
274 /* C_PUT */
275 {L("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 {L("quit"), ex_quit, 0,
282 "!",
283 "q[uit][!]",
284 "exit ex/vi"},
285 /* C_READ */
286 {L("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 {L("recover"), ex_recover, 0,
292 "!f1r",
293 "recover[!] file",
294 "recover a saved file"},
295 /* C_RESIZE */
296 {L("resize"), ex_resize, E_VIONLY,
297 "c+",
298 "resize [+-]rows",
299 "grow or shrink the current screen"},
300 /* C_REWIND */
301 {L("rewind"), ex_rew, 0,
302 "!",
303 "rew[ind][!]",
304 "re-edit all the files in the file argument list"},
306 * !!!
307 * Adding new commands starting with 's' may break the substitute command code
308 * in ex_cmd() (the ex parser). Read through the comments there, first.
310 /* C_SUBSTITUTE */
311 {L("s"), ex_s, E_ADDR2|E_ADDR_ZERO,
312 "s",
313 "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]",
314 "substitute on lines matching an RE"},
315 /* C_SCRIPT */
316 {L("script"), ex_script, E_SECURE,
317 "!f1o",
318 "sc[ript][!] [file]",
319 "run a shell in a screen"},
320 /* C_SET */
321 {L("set"), ex_set, 0,
322 "wN",
323 "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]",
324 "set options (use \":set all\" to see all options)"},
325 /* C_SHELL */
326 {L("shell"), ex_shell, E_SECURE,
328 "sh[ell]",
329 "suspend editing and run a shell"},
330 /* C_SOURCE */
331 {L("source"), ex_source, 0,
332 "f1r",
333 "so[urce] file",
334 "read a file of ex commands"},
335 /* C_STOP */
336 {L("stop"), ex_stop, E_SECURE,
337 "!",
338 "st[op][!]",
339 "suspend the edit session"},
340 /* C_SUSPEND */
341 {L("suspend"), ex_stop, E_SECURE,
342 "!",
343 "su[spend][!]",
344 "suspend the edit session"},
345 /* C_T */
346 {L("t"), ex_copy, E_ADDR2|E_AUTOPRINT,
347 "l1",
348 "[line [,line]] t line [flags]",
349 "copy lines elsewhere in the file"},
350 /* C_TAG */
351 {L("tag"), ex_tag_push, E_NEWSCREEN,
352 "!w1o",
353 "[Tt]a[g][!] [string]",
354 "edit the file containing the tag"},
355 /* C_TAGNEXT */
356 {L("tagnext"), ex_tag_next, 0,
357 "!",
358 "tagn[ext][!]",
359 "move to the next tag"},
360 /* C_TAGPOP */
361 {L("tagpop"), ex_tag_pop, 0,
362 "!w1o",
363 "tagp[op][!] [number | file]",
364 "return to the previous group of tags"},
365 /* C_TAGPREV */
366 {L("tagprev"), ex_tag_prev, 0,
367 "!",
368 "tagpr[ev][!]",
369 "move to the previous tag"},
370 /* C_TAGTOP */
371 {L("tagtop"), ex_tag_top, 0,
372 "!",
373 "tagt[op][!]",
374 "discard all tags"},
375 /* C_TCLCMD */
376 {L("tcl"), ex_tcl, E_ADDR2_ALL|E_ADDR_ZERO|
377 E_ADDR_ZERODEF|E_SECURE,
378 "s",
379 "tc[l] cmd",
380 "run the tcl interpreter with the command"},
381 /* C_UNDO */
382 {L("undo"), ex_undo, E_AUTOPRINT,
384 "u[ndo]",
385 "undo the most recent change"},
386 /* C_UNABBREVIATE */
387 {L("unabbreviate"),ex_unabbr, 0,
388 "w1r",
389 "una[bbrev] word",
390 "delete an abbreviation"},
391 /* C_UNMAP */
392 {L("unmap"), ex_unmap, 0,
393 "!w1r",
394 "unm[ap][!] word",
395 "delete an input or command map"},
396 /* C_V */
397 {L("v"), ex_v, E_ADDR2_ALL,
398 "s",
399 "[line [,line]] v [;/]RE[;/] [commands]",
400 "execute a global command on lines NOT matching an RE"},
401 /* C_VERSION */
402 {L("version"), ex_version, 0,
404 "version",
405 "display the program version information"},
406 /* C_VISUAL_EX */
407 {L("visual"), ex_visual, E_ADDR1|E_ADDR_ZERODEF,
408 "2c11",
409 "[line] vi[sual] [-|.|+|^] [window_size] [flags]",
410 "enter visual (vi) mode from ex mode"},
411 /* C_VISUAL_VI */
412 {L("visual"), ex_edit, E_NEWSCREEN,
413 "f1o",
414 "[Vv]i[sual][!] [+cmd] [file]",
415 "edit another file (from vi mode only)"},
416 /* C_VIUSAGE */
417 {L("viusage"), ex_viusage, 0,
418 "w1o",
419 "[viu]sage [key]",
420 "display vi key usage statement"},
421 /* C_VSPLIT */
422 {L("vsplit"), ex_edit, E_VIONLY,
423 "f1o",
424 "vs[plit] [+cmd] [file]",
425 "split the current screen vertically"},
426 /* C_WRITE */
427 {L("write"), ex_write, E_ADDR2_ALL|E_ADDR_ZERODEF,
428 "!s",
429 "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]",
430 "write the file"},
431 /* C_WN */
432 {L("wn"), ex_wn, E_ADDR2_ALL|E_ADDR_ZERODEF,
433 "!s",
434 "[line [,line]] wn[!] [>>] [file]",
435 "write the file and switch to the next file"},
436 /* C_WQ */
437 {L("wq"), ex_wq, E_ADDR2_ALL|E_ADDR_ZERODEF,
438 "!s",
439 "[line [,line]] wq[!] [>>] [file]",
440 "write the file and exit"},
441 /* C_XIT */
442 {L("xit"), ex_xit, E_ADDR2_ALL|E_ADDR_ZERODEF,
443 "!f1o",
444 "[line [,line]] x[it][!] [file]",
445 "exit"},
446 /* C_YANK */
447 {L("yank"), ex_yank, E_ADDR2,
448 "bca",
449 "[line [,line]] ya[nk] [buffer] [count]",
450 "copy lines to a cut buffer"},
451 /* C_Z */
452 {L("z"), ex_z, E_ADDR1,
453 "3c01",
454 "[line] z [-|.|+|^|=] [count] [flags]",
455 "display different screens of the file"},
456 /* C_SUBTILDE */
457 {L("~"), ex_subtilde, E_ADDR2|E_ADDR_ZERO,
458 "s",
459 "[line [,line]] ~ [cgr] [count] [#lp]",
460 "replace previous RE with previous replacement string,"},
461 {NULL},