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 13 static 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 */ 51 EXCMDLIST 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 subsitution"}, 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 /* 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. 309 */ 310 /* C_SUBSTITUTE */ 311 {"s", ex_s, E_ADDR2, 312 "s", 313 "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]", 314 "substitute on lines matching an RE"}, 315 /* C_SCRIPT */ 316 {"script", ex_script, E_SECURE, 317 "!f1o", 318 "sc[ript][!] [file]", 319 "run a shell in a screen"}, 320 /* C_SET */ 321 {"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 {"shell", ex_shell, E_SECURE, 327 "", 328 "sh[ell]", 329 "suspend editing and run a shell"}, 330 /* C_SOURCE */ 331 {"source", ex_source, 0, 332 "f1r", 333 "so[urce] file", 334 "read a file of ex commands"}, 335 /* C_STOP */ 336 {"stop", ex_stop, E_SECURE, 337 "!", 338 "st[op][!]", 339 "suspend the edit session"}, 340 /* C_SUSPEND */ 341 {"suspend", ex_stop, E_SECURE, 342 "!", 343 "su[spend][!]", 344 "suspend the edit session"}, 345 /* C_T */ 346 {"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 {"tag", ex_tag_push, E_NEWSCREEN, 352 "!w1o", 353 "[Tt]a[g][!] [string]", 354 "edit the file containing the tag"}, 355 /* C_TAGNEXT */ 356 {"tagnext", ex_tag_next, 0, 357 "!", 358 "tagn[ext][!]", 359 "move to the next tag"}, 360 /* C_TAGPOP */ 361 {"tagpop", ex_tag_pop, 0, 362 "!w1o", 363 "tagp[op][!] [number | file]", 364 "return to the previous group of tags"}, 365 /* C_TAGPREV */ 366 {"tagprev", ex_tag_prev, 0, 367 "!", 368 "tagpr[ev][!]", 369 "move to the previous tag"}, 370 /* C_TAGTOP */ 371 {"tagtop", ex_tag_top, 0, 372 "!", 373 "tagt[op][!]", 374 "discard all tags"}, 375 /* C_TCLCMD */ 376 {"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 {"undo", ex_undo, E_AUTOPRINT, 383 "", 384 "u[ndo]", 385 "undo the most recent change"}, 386 /* C_UNABBREVIATE */ 387 {"unabbreviate",ex_unabbr, 0, 388 "w1r", 389 "una[bbrev] word", 390 "delete an abbreviation"}, 391 /* C_UNMAP */ 392 {"unmap", ex_unmap, 0, 393 "!w1r", 394 "unm[ap][!] word", 395 "delete an input or command map"}, 396 /* C_V */ 397 {"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 {"version", ex_version, 0, 403 "", 404 "version", 405 "display the program version information"}, 406 /* C_VISUAL_EX */ 407 {"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 {"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 {"viusage", ex_viusage, 0, 418 "w1o", 419 "[viu]sage [key]", 420 "display vi key usage statement"}, 421 /* C_WRITE */ 422 {"write", ex_write, E_ADDR2_ALL|E_ADDR_ZERODEF, 423 "!s", 424 "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]", 425 "write the file"}, 426 /* C_WN */ 427 {"wn", ex_wn, E_ADDR2_ALL|E_ADDR_ZERODEF, 428 "!s", 429 "[line [,line]] wn[!] [>>] [file]", 430 "write the file and switch to the next file"}, 431 /* C_WQ */ 432 {"wq", ex_wq, E_ADDR2_ALL|E_ADDR_ZERODEF, 433 "!s", 434 "[line [,line]] wq[!] [>>] [file]", 435 "write the file and exit"}, 436 /* C_XIT */ 437 {"xit", ex_xit, E_ADDR2_ALL|E_ADDR_ZERODEF, 438 "!f1o", 439 "[line [,line]] x[it][!] [file]", 440 "exit"}, 441 /* C_YANK */ 442 {"yank", ex_yank, E_ADDR2, 443 "bca", 444 "[line [,line]] ya[nk] [buffer] [count]", 445 "copy lines to a cut buffer"}, 446 /* C_Z */ 447 {"z", ex_z, E_ADDR1, 448 "3c01", 449 "[line] z [-|.|+|^|=] [count] [flags]", 450 "display different screens of the file"}, 451 /* C_SUBTILDE */ 452 {"~", ex_subtilde, E_ADDR2, 453 "s", 454 "[line [,line]] ~ [cgr] [count] [#lp]", 455 "replace previous RE with previous replacement string,"}, 456 {NULL}, 457 }; 458