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