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 */ 48EXCMDLIST 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