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