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