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