119304Speter/*- 219304Speter * Copyright (c) 1992, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 1319304Speterstatic const char sccsid[] = "@(#)ex_cmd.c 10.20 (Berkeley) 10/10/96"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter 1919304Speter#include <bitstring.h> 2019304Speter#include <limits.h> 2119304Speter#include <stdio.h> 2219304Speter 2319304Speter#include "../common/common.h" 2419304Speter 2519304Speter/* 2619304Speter * This array maps ex command names to command functions. 2719304Speter * 2819304Speter * The order in which command names are listed below is important -- 2919304Speter * ambiguous abbreviations are resolved to be the first possible match, 3019304Speter * e.g. "r" means "read", not "rewind", because "read" is listed before 3119304Speter * "rewind". 3219304Speter * 3319304Speter * The syntax of the ex commands is unbelievably irregular, and a special 3419304Speter * case from beginning to end. Each command has an associated "syntax 3519304Speter * script" which describes the "arguments" that are possible. The script 3619304Speter * syntax is as follows: 3719304Speter * 3819304Speter * ! -- ! flag 3919304Speter * 1 -- flags: [+-]*[pl#][+-]* 4019304Speter * 2 -- flags: [-.+^] 4119304Speter * 3 -- flags: [-.+^=] 4219304Speter * b -- buffer 4319304Speter * c[01+a] -- count (0-N, 1-N, signed 1-N, address offset) 4419304Speter * f[N#][or] -- file (a number or N, optional or required) 4519304Speter * l -- line 4619304Speter * S -- string with file name expansion 4719304Speter * s -- string 4819304Speter * W -- word string 4919304Speter * w[N#][or] -- word (a number or N, optional or required) 5019304Speter */ 5119304SpeterEXCMDLIST const cmds[] = { 5219304Speter/* C_SCROLL */ 5319304Speter {"\004", ex_pr, E_ADDR2, 5419304Speter "", 5519304Speter "^D", 5619304Speter "scroll lines"}, 5719304Speter/* C_BANG */ 5819304Speter {"!", ex_bang, E_ADDR2_NONE | E_SECURE, 5919304Speter "S", 6019304Speter "[line [,line]] ! command", 6119304Speter "filter lines through commands or run commands"}, 6219304Speter/* C_HASH */ 6319304Speter {"#", ex_number, E_ADDR2|E_CLRFLAG, 6419304Speter "ca1", 6519304Speter "[line [,line]] # [count] [l]", 6619304Speter "display numbered lines"}, 6719304Speter/* C_SUBAGAIN */ 6819304Speter {"&", ex_subagain, E_ADDR2, 6919304Speter "s", 7019304Speter "[line [,line]] & [cgr] [count] [#lp]", 71208611Sjh "repeat the last substitution"}, 7219304Speter/* C_STAR */ 7319304Speter {"*", ex_at, 0, 7419304Speter "b", 7519304Speter "* [buffer]", 7619304Speter "execute a buffer"}, 7719304Speter/* C_SHIFTL */ 7819304Speter {"<", ex_shiftl, E_ADDR2|E_AUTOPRINT, 7919304Speter "ca1", 8019304Speter "[line [,line]] <[<...] [count] [flags]", 8119304Speter "shift lines left"}, 8219304Speter/* C_EQUAL */ 8319304Speter {"=", ex_equal, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 8419304Speter "1", 8519304Speter "[line] = [flags]", 8619304Speter "display line number"}, 8719304Speter/* C_SHIFTR */ 8819304Speter {">", ex_shiftr, E_ADDR2|E_AUTOPRINT, 8919304Speter "ca1", 9019304Speter "[line [,line]] >[>...] [count] [flags]", 9119304Speter "shift lines right"}, 9219304Speter/* C_AT */ 9319304Speter {"@", ex_at, E_ADDR2, 9419304Speter "b", 9519304Speter "@ [buffer]", 9619304Speter "execute a buffer"}, 9719304Speter/* C_APPEND */ 9819304Speter {"append", ex_append, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 9919304Speter "!", 10019304Speter "[line] a[ppend][!]", 10119304Speter "append input to a line"}, 10219304Speter/* C_ABBR */ 10319304Speter {"abbreviate", ex_abbr, 0, 10419304Speter "W", 10519304Speter "ab[brev] [word replace]", 10619304Speter "specify an input abbreviation"}, 10719304Speter/* C_ARGS */ 10819304Speter {"args", ex_args, 0, 10919304Speter "", 11019304Speter "ar[gs]", 11119304Speter "display file argument list"}, 11219304Speter/* C_BG */ 11319304Speter {"bg", ex_bg, E_VIONLY, 11419304Speter "", 11519304Speter "bg", 11619304Speter "put a foreground screen into the background"}, 11719304Speter/* C_CHANGE */ 11819304Speter {"change", ex_change, E_ADDR2|E_ADDR_ZERODEF, 11919304Speter "!ca", 12019304Speter "[line [,line]] c[hange][!] [count]", 12119304Speter "change lines to input"}, 12219304Speter/* C_CD */ 12319304Speter {"cd", ex_cd, 0, 12419304Speter "!f1o", 12519304Speter "cd[!] [directory]", 12619304Speter "change the current directory"}, 12719304Speter/* C_CHDIR */ 12819304Speter {"chdir", ex_cd, 0, 12919304Speter "!f1o", 13019304Speter "chd[ir][!] [directory]", 13119304Speter "change the current directory"}, 13219304Speter/* C_COPY */ 13319304Speter {"copy", ex_copy, E_ADDR2|E_AUTOPRINT, 13419304Speter "l1", 13519304Speter "[line [,line]] co[py] line [flags]", 13619304Speter "copy lines elsewhere in the file"}, 13719304Speter/* C_CSCOPE */ 13819304Speter {"cscope", ex_cscope, 0, 13919304Speter "!s", 14019304Speter "cs[cope] command [args]", 14119304Speter "create a set of tags using a cscope command"}, 14219304Speter/* 14319304Speter * !!! 14419304Speter * Adding new commands starting with 'd' may break the delete command code 14519304Speter * in ex_cmd() (the ex parser). Read through the comments there, first. 14619304Speter */ 14719304Speter/* C_DELETE */ 14819304Speter {"delete", ex_delete, E_ADDR2|E_AUTOPRINT, 14919304Speter "bca1", 15019304Speter "[line [,line]] d[elete][flags] [buffer] [count] [flags]", 15119304Speter "delete lines from the file"}, 15219304Speter/* C_DISPLAY */ 15319304Speter {"display", ex_display, 0, 15419304Speter "w1r", 15519304Speter "display b[uffers] | c[onnections] | s[creens] | t[ags]", 15619304Speter "display buffers, connections, screens or tags"}, 15719304Speter/* C_EDIT */ 15819304Speter {"edit", ex_edit, E_NEWSCREEN, 15919304Speter "f1o", 16019304Speter "[Ee][dit][!] [+cmd] [file]", 16119304Speter "begin editing another file"}, 16219304Speter/* C_EX */ 16319304Speter {"ex", ex_edit, E_NEWSCREEN, 16419304Speter "f1o", 16519304Speter "[Ee]x[!] [+cmd] [file]", 16619304Speter "begin editing another file"}, 16719304Speter/* C_EXUSAGE */ 16819304Speter {"exusage", ex_usage, 0, 16919304Speter "w1o", 17019304Speter "[exu]sage [command]", 17119304Speter "display ex command usage statement"}, 17219304Speter/* C_FILE */ 17319304Speter {"file", ex_file, 0, 17419304Speter "f1o", 17519304Speter "f[ile] [name]", 17619304Speter "display (and optionally set) file name"}, 17719304Speter/* C_FG */ 17819304Speter {"fg", ex_fg, E_NEWSCREEN|E_VIONLY, 17919304Speter "f1o", 18019304Speter "[Ff]g [file]", 18119304Speter "bring a backgrounded screen into the foreground"}, 18219304Speter/* C_GLOBAL */ 18319304Speter {"global", ex_global, E_ADDR2_ALL, 18419304Speter "!s", 18519304Speter "[line [,line]] g[lobal][!] [;/]RE[;/] [commands]", 18619304Speter "execute a global command on lines matching an RE"}, 18719304Speter/* C_HELP */ 18819304Speter {"help", ex_help, 0, 18919304Speter "", 19019304Speter "he[lp]", 19119304Speter "display help statement"}, 19219304Speter/* C_INSERT */ 19319304Speter {"insert", ex_insert, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 19419304Speter "!", 19519304Speter "[line] i[nsert][!]", 19619304Speter "insert input before a line"}, 19719304Speter/* C_JOIN */ 19819304Speter {"join", ex_join, E_ADDR2|E_AUTOPRINT, 19919304Speter "!ca1", 20019304Speter "[line [,line]] j[oin][!] [count] [flags]", 20119304Speter "join lines into a single line"}, 20219304Speter/* C_K */ 20319304Speter {"k", ex_mark, E_ADDR1, 20419304Speter "w1r", 20519304Speter "[line] k key", 20619304Speter "mark a line position"}, 20719304Speter/* C_LIST */ 20819304Speter {"list", ex_list, E_ADDR2|E_CLRFLAG, 20919304Speter "ca1", 21019304Speter "[line [,line]] l[ist] [count] [#]", 21119304Speter "display lines in an unambiguous form"}, 21219304Speter/* C_MOVE */ 21319304Speter {"move", ex_move, E_ADDR2|E_AUTOPRINT, 21419304Speter "l", 21519304Speter "[line [,line]] m[ove] line", 21619304Speter "move lines elsewhere in the file"}, 21719304Speter/* C_MARK */ 21819304Speter {"mark", ex_mark, E_ADDR1, 21919304Speter "w1r", 22019304Speter "[line] ma[rk] key", 22119304Speter "mark a line position"}, 22219304Speter/* C_MAP */ 22319304Speter {"map", ex_map, 0, 22419304Speter "!W", 22519304Speter "map[!] [keys replace]", 22619304Speter "map input or commands to one or more keys"}, 22719304Speter/* C_MKEXRC */ 22819304Speter {"mkexrc", ex_mkexrc, 0, 22919304Speter "!f1r", 23019304Speter "mkexrc[!] file", 23119304Speter "write a .exrc file"}, 23219304Speter/* C_NEXT */ 23319304Speter {"next", ex_next, E_NEWSCREEN, 23419304Speter "!fN", 23519304Speter "[Nn][ext][!] [+cmd] [file ...]", 23619304Speter "edit (and optionally specify) the next file"}, 23719304Speter/* C_NUMBER */ 23819304Speter {"number", ex_number, E_ADDR2|E_CLRFLAG, 23919304Speter "ca1", 24019304Speter "[line [,line]] nu[mber] [count] [l]", 24119304Speter "change display to number lines"}, 24219304Speter/* C_OPEN */ 24319304Speter {"open", ex_open, E_ADDR1, 24419304Speter "s", 24519304Speter "[line] o[pen] [/RE/] [flags]", 24619304Speter "enter \"open\" mode (not implemented)"}, 24719304Speter/* C_PRINT */ 24819304Speter {"print", ex_pr, E_ADDR2|E_CLRFLAG, 24919304Speter "ca1", 25019304Speter "[line [,line]] p[rint] [count] [#l]", 25119304Speter "display lines"}, 25219304Speter/* C_PERLCMD */ 25319304Speter {"perl", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO| 25419304Speter E_ADDR_ZERODEF|E_SECURE, 25519304Speter "s", 25619304Speter "pe[rl] cmd", 25719304Speter "run the perl interpreter with the command"}, 25819304Speter/* C_PERLDOCMD */ 25919304Speter {"perldo", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO| 26019304Speter E_ADDR_ZERODEF|E_SECURE, 26119304Speter "s", 26219304Speter "perld[o] cmd", 26319304Speter "run the perl interpreter with the command, on each line"}, 26419304Speter/* C_PRESERVE */ 26519304Speter {"preserve", ex_preserve, 0, 26619304Speter "", 26719304Speter "pre[serve]", 26819304Speter "preserve an edit session for recovery"}, 26919304Speter/* C_PREVIOUS */ 27019304Speter {"previous", ex_prev, E_NEWSCREEN, 27119304Speter "!", 27219304Speter "[Pp]rev[ious][!]", 27319304Speter "edit the previous file in the file argument list"}, 27419304Speter/* C_PUT */ 27519304Speter {"put", ex_put, 27619304Speter E_ADDR1|E_AUTOPRINT|E_ADDR_ZERO|E_ADDR_ZERODEF, 27719304Speter "b", 27819304Speter "[line] pu[t] [buffer]", 27919304Speter "append a cut buffer to the line"}, 28019304Speter/* C_QUIT */ 28119304Speter {"quit", ex_quit, 0, 28219304Speter "!", 28319304Speter "q[uit][!]", 28419304Speter "exit ex/vi"}, 28519304Speter/* C_READ */ 28619304Speter {"read", ex_read, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 28719304Speter "s", 28819304Speter "[line] r[ead] [!cmd | [file]]", 28919304Speter "append input from a command or file to the line"}, 29019304Speter/* C_RECOVER */ 29119304Speter {"recover", ex_recover, 0, 29219304Speter "!f1r", 29319304Speter "recover[!] file", 29419304Speter "recover a saved file"}, 29519304Speter/* C_RESIZE */ 29619304Speter {"resize", ex_resize, E_VIONLY, 29719304Speter "c+", 29819304Speter "resize [+-]rows", 29919304Speter "grow or shrink the current screen"}, 30019304Speter/* C_REWIND */ 30119304Speter {"rewind", ex_rew, 0, 30219304Speter "!", 30319304Speter "rew[ind][!]", 30419304Speter "re-edit all the files in the file argument list"}, 30525011Sjkh#ifdef GTAGS 30625011Sjkh/* C_RTAG */ 30725011Sjkh {"rtag", ex_rtag_push, E_NEWSCREEN, 30825011Sjkh "!w1o", 30925011Sjkh "[Rr]ta[g][!] [string]", 31025011Sjkh "edit the file containing the tag"}, 31125011Sjkh#endif 31219304Speter/* 31319304Speter * !!! 31419304Speter * Adding new commands starting with 's' may break the substitute command code 31519304Speter * in ex_cmd() (the ex parser). Read through the comments there, first. 31619304Speter */ 31719304Speter/* C_SUBSTITUTE */ 31819304Speter {"s", ex_s, E_ADDR2, 31919304Speter "s", 32019304Speter "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]", 32119304Speter "substitute on lines matching an RE"}, 32219304Speter/* C_SCRIPT */ 32319304Speter {"script", ex_script, E_SECURE, 32419304Speter "!f1o", 32519304Speter "sc[ript][!] [file]", 32619304Speter "run a shell in a screen"}, 32719304Speter/* C_SET */ 32819304Speter {"set", ex_set, 0, 32919304Speter "wN", 33019304Speter "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]", 33119304Speter "set options (use \":set all\" to see all options)"}, 33219304Speter/* C_SHELL */ 33319304Speter {"shell", ex_shell, E_SECURE, 33419304Speter "", 33519304Speter "sh[ell]", 33619304Speter "suspend editing and run a shell"}, 33719304Speter/* C_SOURCE */ 33819304Speter {"source", ex_source, 0, 33919304Speter "f1r", 34019304Speter "so[urce] file", 34119304Speter "read a file of ex commands"}, 34219304Speter/* C_STOP */ 34319304Speter {"stop", ex_stop, E_SECURE, 34419304Speter "!", 34519304Speter "st[op][!]", 34619304Speter "suspend the edit session"}, 34719304Speter/* C_SUSPEND */ 34819304Speter {"suspend", ex_stop, E_SECURE, 34919304Speter "!", 35019304Speter "su[spend][!]", 35119304Speter "suspend the edit session"}, 35219304Speter/* C_T */ 35319304Speter {"t", ex_copy, E_ADDR2|E_AUTOPRINT, 35419304Speter "l1", 35519304Speter "[line [,line]] t line [flags]", 35619304Speter "copy lines elsewhere in the file"}, 35719304Speter/* C_TAG */ 35819304Speter {"tag", ex_tag_push, E_NEWSCREEN, 35919304Speter "!w1o", 36019304Speter "[Tt]a[g][!] [string]", 36119304Speter "edit the file containing the tag"}, 36219304Speter/* C_TAGNEXT */ 36319304Speter {"tagnext", ex_tag_next, 0, 36419304Speter "!", 36519304Speter "tagn[ext][!]", 36619304Speter "move to the next tag"}, 36719304Speter/* C_TAGPOP */ 36819304Speter {"tagpop", ex_tag_pop, 0, 36919304Speter "!w1o", 37019304Speter "tagp[op][!] [number | file]", 37119304Speter "return to the previous group of tags"}, 37219304Speter/* C_TAGPREV */ 37319304Speter {"tagprev", ex_tag_prev, 0, 37419304Speter "!", 37519304Speter "tagpr[ev][!]", 37619304Speter "move to the previous tag"}, 37719304Speter/* C_TAGTOP */ 37819304Speter {"tagtop", ex_tag_top, 0, 37919304Speter "!", 38019304Speter "tagt[op][!]", 38119304Speter "discard all tags"}, 38219304Speter/* C_TCLCMD */ 38319304Speter {"tcl", ex_tcl, E_ADDR2_ALL|E_ADDR_ZERO| 38419304Speter E_ADDR_ZERODEF|E_SECURE, 38519304Speter "s", 38619304Speter "tc[l] cmd", 38719304Speter "run the tcl interpreter with the command"}, 38819304Speter/* C_UNDO */ 38919304Speter {"undo", ex_undo, E_AUTOPRINT, 39019304Speter "", 39119304Speter "u[ndo]", 39219304Speter "undo the most recent change"}, 39319304Speter/* C_UNABBREVIATE */ 39419304Speter {"unabbreviate",ex_unabbr, 0, 39519304Speter "w1r", 39619304Speter "una[bbrev] word", 39719304Speter "delete an abbreviation"}, 39819304Speter/* C_UNMAP */ 39919304Speter {"unmap", ex_unmap, 0, 40019304Speter "!w1r", 40119304Speter "unm[ap][!] word", 40219304Speter "delete an input or command map"}, 40319304Speter/* C_V */ 40419304Speter {"v", ex_v, E_ADDR2_ALL, 40519304Speter "s", 40619304Speter "[line [,line]] v [;/]RE[;/] [commands]", 40719304Speter "execute a global command on lines NOT matching an RE"}, 40819304Speter/* C_VERSION */ 40919304Speter {"version", ex_version, 0, 41019304Speter "", 41119304Speter "version", 41219304Speter "display the program version information"}, 41319304Speter/* C_VISUAL_EX */ 41419304Speter {"visual", ex_visual, E_ADDR1|E_ADDR_ZERODEF, 41519304Speter "2c11", 41619304Speter "[line] vi[sual] [-|.|+|^] [window_size] [flags]", 41719304Speter "enter visual (vi) mode from ex mode"}, 41819304Speter/* C_VISUAL_VI */ 41919304Speter {"visual", ex_edit, E_NEWSCREEN, 42019304Speter "f1o", 42119304Speter "[Vv]i[sual][!] [+cmd] [file]", 42219304Speter "edit another file (from vi mode only)"}, 42319304Speter/* C_VIUSAGE */ 42419304Speter {"viusage", ex_viusage, 0, 42519304Speter "w1o", 42619304Speter "[viu]sage [key]", 42719304Speter "display vi key usage statement"}, 42819304Speter/* C_WRITE */ 42919304Speter {"write", ex_write, E_ADDR2_ALL|E_ADDR_ZERODEF, 43019304Speter "!s", 43119304Speter "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]", 43219304Speter "write the file"}, 43319304Speter/* C_WN */ 43419304Speter {"wn", ex_wn, E_ADDR2_ALL|E_ADDR_ZERODEF, 43519304Speter "!s", 43619304Speter "[line [,line]] wn[!] [>>] [file]", 43719304Speter "write the file and switch to the next file"}, 43819304Speter/* C_WQ */ 43919304Speter {"wq", ex_wq, E_ADDR2_ALL|E_ADDR_ZERODEF, 44019304Speter "!s", 44119304Speter "[line [,line]] wq[!] [>>] [file]", 44219304Speter "write the file and exit"}, 44319304Speter/* C_XIT */ 44419304Speter {"xit", ex_xit, E_ADDR2_ALL|E_ADDR_ZERODEF, 44519304Speter "!f1o", 44619304Speter "[line [,line]] x[it][!] [file]", 44719304Speter "exit"}, 44819304Speter/* C_YANK */ 44919304Speter {"yank", ex_yank, E_ADDR2, 45019304Speter "bca", 45119304Speter "[line [,line]] ya[nk] [buffer] [count]", 45219304Speter "copy lines to a cut buffer"}, 45319304Speter/* C_Z */ 45419304Speter {"z", ex_z, E_ADDR1, 45519304Speter "3c01", 45619304Speter "[line] z [-|.|+|^|=] [count] [flags]", 45719304Speter "display different screens of the file"}, 45819304Speter/* C_SUBTILDE */ 45919304Speter {"~", ex_subtilde, E_ADDR2, 46019304Speter "s", 46119304Speter "[line [,line]] ~ [cgr] [count] [#lp]", 46219304Speter "replace previous RE with previous replacement string,"}, 46319304Speter {NULL}, 46419304Speter}; 465