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 13254225Speterstatic const char sccsid[] = "$Id: ex_cmd.c,v 10.26 2011/07/14 15:11:16 zy Exp $"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 18254225Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <limits.h> 2219304Speter#include <stdio.h> 2319304Speter 2419304Speter#include "../common/common.h" 2519304Speter 2619304Speter/* 2719304Speter * This array maps ex command names to command functions. 2819304Speter * 2919304Speter * The order in which command names are listed below is important -- 3019304Speter * ambiguous abbreviations are resolved to be the first possible match, 3119304Speter * e.g. "r" means "read", not "rewind", because "read" is listed before 3219304Speter * "rewind". 3319304Speter * 3419304Speter * The syntax of the ex commands is unbelievably irregular, and a special 3519304Speter * case from beginning to end. Each command has an associated "syntax 3619304Speter * script" which describes the "arguments" that are possible. The script 3719304Speter * syntax is as follows: 3819304Speter * 3919304Speter * ! -- ! flag 4019304Speter * 1 -- flags: [+-]*[pl#][+-]* 4119304Speter * 2 -- flags: [-.+^] 4219304Speter * 3 -- flags: [-.+^=] 4319304Speter * b -- buffer 4419304Speter * c[01+a] -- count (0-N, 1-N, signed 1-N, address offset) 4519304Speter * f[N#][or] -- file (a number or N, optional or required) 4619304Speter * l -- line 4719304Speter * S -- string with file name expansion 4819304Speter * s -- string 4919304Speter * W -- word string 5019304Speter * w[N#][or] -- word (a number or N, optional or required) 5119304Speter */ 5219304SpeterEXCMDLIST const cmds[] = { 5319304Speter/* C_SCROLL */ 54254225Speter {L("\004"), ex_pr, E_ADDR2, 5519304Speter "", 5619304Speter "^D", 5719304Speter "scroll lines"}, 5819304Speter/* C_BANG */ 59254225Speter {L("!"), ex_bang, E_ADDR2_NONE|E_SECURE, 6019304Speter "S", 6119304Speter "[line [,line]] ! command", 6219304Speter "filter lines through commands or run commands"}, 6319304Speter/* C_HASH */ 64254225Speter {L("#"), ex_number, E_ADDR2|E_CLRFLAG, 6519304Speter "ca1", 6619304Speter "[line [,line]] # [count] [l]", 6719304Speter "display numbered lines"}, 6819304Speter/* C_SUBAGAIN */ 69254225Speter {L("&"), ex_subagain, E_ADDR2|E_ADDR_ZERO, 7019304Speter "s", 7119304Speter "[line [,line]] & [cgr] [count] [#lp]", 72254225Speter "repeat the last subsitution"}, 7319304Speter/* C_STAR */ 74254225Speter {L("*"), ex_at, 0, 7519304Speter "b", 7619304Speter "* [buffer]", 7719304Speter "execute a buffer"}, 7819304Speter/* C_SHIFTL */ 79254225Speter {L("<"), ex_shiftl, E_ADDR2|E_AUTOPRINT, 8019304Speter "ca1", 8119304Speter "[line [,line]] <[<...] [count] [flags]", 8219304Speter "shift lines left"}, 8319304Speter/* C_EQUAL */ 84254225Speter {L("="), ex_equal, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 8519304Speter "1", 8619304Speter "[line] = [flags]", 8719304Speter "display line number"}, 8819304Speter/* C_SHIFTR */ 89254225Speter {L(">"), ex_shiftr, E_ADDR2|E_AUTOPRINT, 9019304Speter "ca1", 9119304Speter "[line [,line]] >[>...] [count] [flags]", 9219304Speter "shift lines right"}, 9319304Speter/* C_AT */ 94254225Speter {L("@"), ex_at, E_ADDR2, 9519304Speter "b", 9619304Speter "@ [buffer]", 9719304Speter "execute a buffer"}, 9819304Speter/* C_APPEND */ 99254225Speter {L("append"), ex_append, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 10019304Speter "!", 10119304Speter "[line] a[ppend][!]", 10219304Speter "append input to a line"}, 10319304Speter/* C_ABBR */ 104254225Speter {L("abbreviate"), ex_abbr, 0, 10519304Speter "W", 10619304Speter "ab[brev] [word replace]", 10719304Speter "specify an input abbreviation"}, 10819304Speter/* C_ARGS */ 109254225Speter {L("args"), ex_args, 0, 11019304Speter "", 11119304Speter "ar[gs]", 11219304Speter "display file argument list"}, 11319304Speter/* C_BG */ 114254225Speter {L("bg"), ex_bg, E_VIONLY, 11519304Speter "", 11619304Speter "bg", 11719304Speter "put a foreground screen into the background"}, 11819304Speter/* C_CHANGE */ 119254225Speter {L("change"), ex_change, E_ADDR2|E_ADDR_ZERODEF, 12019304Speter "!ca", 12119304Speter "[line [,line]] c[hange][!] [count]", 12219304Speter "change lines to input"}, 12319304Speter/* C_CD */ 124254225Speter {L("cd"), ex_cd, 0, 12519304Speter "!f1o", 12619304Speter "cd[!] [directory]", 12719304Speter "change the current directory"}, 12819304Speter/* C_CHDIR */ 129254225Speter {L("chdir"), ex_cd, 0, 13019304Speter "!f1o", 13119304Speter "chd[ir][!] [directory]", 13219304Speter "change the current directory"}, 13319304Speter/* C_COPY */ 134254225Speter {L("copy"), ex_copy, E_ADDR2|E_AUTOPRINT, 13519304Speter "l1", 13619304Speter "[line [,line]] co[py] line [flags]", 13719304Speter "copy lines elsewhere in the file"}, 13819304Speter/* C_CSCOPE */ 139254225Speter {L("cscope"), ex_cscope, 0, 14019304Speter "!s", 14119304Speter "cs[cope] command [args]", 14219304Speter "create a set of tags using a cscope command"}, 14319304Speter/* 14419304Speter * !!! 14519304Speter * Adding new commands starting with 'd' may break the delete command code 14619304Speter * in ex_cmd() (the ex parser). Read through the comments there, first. 14719304Speter */ 14819304Speter/* C_DELETE */ 149254225Speter {L("delete"), ex_delete, E_ADDR2|E_AUTOPRINT, 15019304Speter "bca1", 15119304Speter "[line [,line]] d[elete][flags] [buffer] [count] [flags]", 15219304Speter "delete lines from the file"}, 15319304Speter/* C_DISPLAY */ 154254225Speter {L("display"), ex_display, 0, 15519304Speter "w1r", 15619304Speter "display b[uffers] | c[onnections] | s[creens] | t[ags]", 15719304Speter "display buffers, connections, screens or tags"}, 15819304Speter/* C_EDIT */ 159254225Speter {L("edit"), ex_edit, E_NEWSCREEN, 16019304Speter "f1o", 16119304Speter "[Ee][dit][!] [+cmd] [file]", 16219304Speter "begin editing another file"}, 16319304Speter/* C_EX */ 164254225Speter {L("ex"), ex_edit, E_NEWSCREEN, 16519304Speter "f1o", 16619304Speter "[Ee]x[!] [+cmd] [file]", 16719304Speter "begin editing another file"}, 16819304Speter/* C_EXUSAGE */ 169254225Speter {L("exusage"), ex_usage, 0, 17019304Speter "w1o", 17119304Speter "[exu]sage [command]", 17219304Speter "display ex command usage statement"}, 17319304Speter/* C_FILE */ 174254225Speter {L("file"), ex_file, 0, 17519304Speter "f1o", 17619304Speter "f[ile] [name]", 17719304Speter "display (and optionally set) file name"}, 17819304Speter/* C_FG */ 179254225Speter {L("fg"), ex_fg, E_NEWSCREEN|E_VIONLY, 18019304Speter "f1o", 18119304Speter "[Ff]g [file]", 18219304Speter "bring a backgrounded screen into the foreground"}, 18319304Speter/* C_GLOBAL */ 184254225Speter {L("global"), ex_global, E_ADDR2_ALL, 18519304Speter "!s", 18619304Speter "[line [,line]] g[lobal][!] [;/]RE[;/] [commands]", 18719304Speter "execute a global command on lines matching an RE"}, 18819304Speter/* C_HELP */ 189254225Speter {L("help"), ex_help, 0, 19019304Speter "", 19119304Speter "he[lp]", 19219304Speter "display help statement"}, 19319304Speter/* C_INSERT */ 194254225Speter {L("insert"), ex_insert, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 19519304Speter "!", 19619304Speter "[line] i[nsert][!]", 19719304Speter "insert input before a line"}, 19819304Speter/* C_JOIN */ 199254225Speter {L("join"), ex_join, E_ADDR2|E_AUTOPRINT, 20019304Speter "!ca1", 20119304Speter "[line [,line]] j[oin][!] [count] [flags]", 20219304Speter "join lines into a single line"}, 20319304Speter/* C_K */ 204254225Speter {L("k"), ex_mark, E_ADDR1, 20519304Speter "w1r", 20619304Speter "[line] k key", 20719304Speter "mark a line position"}, 20819304Speter/* C_LIST */ 209254225Speter {L("list"), ex_list, E_ADDR2|E_CLRFLAG, 21019304Speter "ca1", 21119304Speter "[line [,line]] l[ist] [count] [#]", 21219304Speter "display lines in an unambiguous form"}, 21319304Speter/* C_MOVE */ 214254225Speter {L("move"), ex_move, E_ADDR2|E_AUTOPRINT, 21519304Speter "l", 21619304Speter "[line [,line]] m[ove] line", 21719304Speter "move lines elsewhere in the file"}, 21819304Speter/* C_MARK */ 219254225Speter {L("mark"), ex_mark, E_ADDR1, 22019304Speter "w1r", 22119304Speter "[line] ma[rk] key", 22219304Speter "mark a line position"}, 22319304Speter/* C_MAP */ 224254225Speter {L("map"), ex_map, 0, 22519304Speter "!W", 22619304Speter "map[!] [keys replace]", 22719304Speter "map input or commands to one or more keys"}, 22819304Speter/* C_MKEXRC */ 229254225Speter {L("mkexrc"), ex_mkexrc, 0, 23019304Speter "!f1r", 23119304Speter "mkexrc[!] file", 23219304Speter "write a .exrc file"}, 23319304Speter/* C_NEXT */ 234254225Speter {L("next"), ex_next, E_NEWSCREEN, 23519304Speter "!fN", 23619304Speter "[Nn][ext][!] [+cmd] [file ...]", 23719304Speter "edit (and optionally specify) the next file"}, 23819304Speter/* C_NUMBER */ 239254225Speter {L("number"), ex_number, E_ADDR2|E_CLRFLAG, 24019304Speter "ca1", 24119304Speter "[line [,line]] nu[mber] [count] [l]", 24219304Speter "change display to number lines"}, 24319304Speter/* C_OPEN */ 244254225Speter {L("open"), ex_open, E_ADDR1, 24519304Speter "s", 24619304Speter "[line] o[pen] [/RE/] [flags]", 24719304Speter "enter \"open\" mode (not implemented)"}, 24819304Speter/* C_PRINT */ 249254225Speter {L("print"), ex_pr, E_ADDR2|E_CLRFLAG, 25019304Speter "ca1", 25119304Speter "[line [,line]] p[rint] [count] [#l]", 25219304Speter "display lines"}, 25319304Speter/* C_PRESERVE */ 254254225Speter {L("preserve"), ex_preserve, 0, 25519304Speter "", 25619304Speter "pre[serve]", 25719304Speter "preserve an edit session for recovery"}, 25819304Speter/* C_PREVIOUS */ 259254225Speter {L("previous"), ex_prev, E_NEWSCREEN, 26019304Speter "!", 26119304Speter "[Pp]rev[ious][!]", 26219304Speter "edit the previous file in the file argument list"}, 26319304Speter/* C_PUT */ 264254225Speter {L("put"), ex_put, 26519304Speter E_ADDR1|E_AUTOPRINT|E_ADDR_ZERO|E_ADDR_ZERODEF, 26619304Speter "b", 26719304Speter "[line] pu[t] [buffer]", 26819304Speter "append a cut buffer to the line"}, 26919304Speter/* C_QUIT */ 270254225Speter {L("quit"), ex_quit, 0, 27119304Speter "!", 27219304Speter "q[uit][!]", 27319304Speter "exit ex/vi"}, 27419304Speter/* C_READ */ 275254225Speter {L("read"), ex_read, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF, 27619304Speter "s", 27719304Speter "[line] r[ead] [!cmd | [file]]", 27819304Speter "append input from a command or file to the line"}, 27919304Speter/* C_RECOVER */ 280254225Speter {L("recover"), ex_recover, 0, 28119304Speter "!f1r", 28219304Speter "recover[!] file", 28319304Speter "recover a saved file"}, 28419304Speter/* C_RESIZE */ 285254225Speter {L("resize"), ex_resize, E_VIONLY, 28619304Speter "c+", 28719304Speter "resize [+-]rows", 28819304Speter "grow or shrink the current screen"}, 28919304Speter/* C_REWIND */ 290254225Speter {L("rewind"), ex_rew, 0, 29119304Speter "!", 29219304Speter "rew[ind][!]", 29319304Speter "re-edit all the files in the file argument list"}, 29419304Speter/* 29519304Speter * !!! 29619304Speter * Adding new commands starting with 's' may break the substitute command code 29719304Speter * in ex_cmd() (the ex parser). Read through the comments there, first. 29819304Speter */ 29919304Speter/* C_SUBSTITUTE */ 300254225Speter {L("s"), ex_s, E_ADDR2|E_ADDR_ZERO, 30119304Speter "s", 30219304Speter "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]", 30319304Speter "substitute on lines matching an RE"}, 30419304Speter/* C_SCRIPT */ 305254225Speter {L("script"), ex_script, E_SECURE, 30619304Speter "!f1o", 30719304Speter "sc[ript][!] [file]", 30819304Speter "run a shell in a screen"}, 30919304Speter/* C_SET */ 310254225Speter {L("set"), ex_set, 0, 31119304Speter "wN", 31219304Speter "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]", 31319304Speter "set options (use \":set all\" to see all options)"}, 31419304Speter/* C_SHELL */ 315254225Speter {L("shell"), ex_shell, E_SECURE, 31619304Speter "", 31719304Speter "sh[ell]", 31819304Speter "suspend editing and run a shell"}, 31919304Speter/* C_SOURCE */ 320254225Speter {L("source"), ex_source, 0, 32119304Speter "f1r", 32219304Speter "so[urce] file", 32319304Speter "read a file of ex commands"}, 32419304Speter/* C_STOP */ 325254225Speter {L("stop"), ex_stop, E_SECURE, 32619304Speter "!", 32719304Speter "st[op][!]", 32819304Speter "suspend the edit session"}, 32919304Speter/* C_SUSPEND */ 330254225Speter {L("suspend"), ex_stop, E_SECURE, 33119304Speter "!", 33219304Speter "su[spend][!]", 33319304Speter "suspend the edit session"}, 33419304Speter/* C_T */ 335254225Speter {L("t"), ex_copy, E_ADDR2|E_AUTOPRINT, 33619304Speter "l1", 33719304Speter "[line [,line]] t line [flags]", 33819304Speter "copy lines elsewhere in the file"}, 33919304Speter/* C_TAG */ 340254225Speter {L("tag"), ex_tag_push, E_NEWSCREEN, 34119304Speter "!w1o", 34219304Speter "[Tt]a[g][!] [string]", 34319304Speter "edit the file containing the tag"}, 34419304Speter/* C_TAGNEXT */ 345254225Speter {L("tagnext"), ex_tag_next, 0, 34619304Speter "!", 34719304Speter "tagn[ext][!]", 34819304Speter "move to the next tag"}, 34919304Speter/* C_TAGPOP */ 350254225Speter {L("tagpop"), ex_tag_pop, 0, 35119304Speter "!w1o", 35219304Speter "tagp[op][!] [number | file]", 35319304Speter "return to the previous group of tags"}, 35419304Speter/* C_TAGPREV */ 355254225Speter {L("tagprev"), ex_tag_prev, 0, 35619304Speter "!", 35719304Speter "tagpr[ev][!]", 35819304Speter "move to the previous tag"}, 35919304Speter/* C_TAGTOP */ 360254225Speter {L("tagtop"), ex_tag_top, 0, 36119304Speter "!", 36219304Speter "tagt[op][!]", 36319304Speter "discard all tags"}, 36419304Speter/* C_UNDO */ 365254225Speter {L("undo"), ex_undo, E_AUTOPRINT, 36619304Speter "", 36719304Speter "u[ndo]", 36819304Speter "undo the most recent change"}, 36919304Speter/* C_UNABBREVIATE */ 370254225Speter {L("unabbreviate"),ex_unabbr, 0, 37119304Speter "w1r", 37219304Speter "una[bbrev] word", 37319304Speter "delete an abbreviation"}, 37419304Speter/* C_UNMAP */ 375254225Speter {L("unmap"), ex_unmap, 0, 37619304Speter "!w1r", 37719304Speter "unm[ap][!] word", 37819304Speter "delete an input or command map"}, 37919304Speter/* C_V */ 380254225Speter {L("v"), ex_v, E_ADDR2_ALL, 38119304Speter "s", 38219304Speter "[line [,line]] v [;/]RE[;/] [commands]", 38319304Speter "execute a global command on lines NOT matching an RE"}, 38419304Speter/* C_VERSION */ 385254225Speter {L("version"), ex_version, 0, 38619304Speter "", 38719304Speter "version", 38819304Speter "display the program version information"}, 38919304Speter/* C_VISUAL_EX */ 390254225Speter {L("visual"), ex_visual, E_ADDR1|E_ADDR_ZERODEF, 39119304Speter "2c11", 39219304Speter "[line] vi[sual] [-|.|+|^] [window_size] [flags]", 39319304Speter "enter visual (vi) mode from ex mode"}, 39419304Speter/* C_VISUAL_VI */ 395254225Speter {L("visual"), ex_edit, E_NEWSCREEN, 39619304Speter "f1o", 39719304Speter "[Vv]i[sual][!] [+cmd] [file]", 39819304Speter "edit another file (from vi mode only)"}, 39919304Speter/* C_VIUSAGE */ 400254225Speter {L("viusage"), ex_viusage, 0, 40119304Speter "w1o", 40219304Speter "[viu]sage [key]", 40319304Speter "display vi key usage statement"}, 404254225Speter/* C_VSPLIT */ 405254225Speter {L("vsplit"), ex_edit, E_VIONLY, 406254225Speter "f1o", 407254225Speter "vs[plit] [+cmd] [file]", 408254225Speter "split the current screen vertically"}, 40919304Speter/* C_WRITE */ 410254225Speter {L("write"), ex_write, E_ADDR2_ALL|E_ADDR_ZERODEF, 41119304Speter "!s", 41219304Speter "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]", 41319304Speter "write the file"}, 41419304Speter/* C_WN */ 415254225Speter {L("wn"), ex_wn, E_ADDR2_ALL|E_ADDR_ZERODEF, 41619304Speter "!s", 41719304Speter "[line [,line]] wn[!] [>>] [file]", 41819304Speter "write the file and switch to the next file"}, 41919304Speter/* C_WQ */ 420254225Speter {L("wq"), ex_wq, E_ADDR2_ALL|E_ADDR_ZERODEF, 42119304Speter "!s", 42219304Speter "[line [,line]] wq[!] [>>] [file]", 42319304Speter "write the file and exit"}, 42419304Speter/* C_XIT */ 425254225Speter {L("xit"), ex_xit, E_ADDR2_ALL|E_ADDR_ZERODEF, 42619304Speter "!f1o", 42719304Speter "[line [,line]] x[it][!] [file]", 42819304Speter "exit"}, 42919304Speter/* C_YANK */ 430254225Speter {L("yank"), ex_yank, E_ADDR2, 43119304Speter "bca", 43219304Speter "[line [,line]] ya[nk] [buffer] [count]", 43319304Speter "copy lines to a cut buffer"}, 43419304Speter/* C_Z */ 435254225Speter {L("z"), ex_z, E_ADDR1, 43619304Speter "3c01", 43719304Speter "[line] z [-|.|+|^|=] [count] [flags]", 43819304Speter "display different screens of the file"}, 43919304Speter/* C_SUBTILDE */ 440254225Speter {L("~"), ex_subtilde, E_ADDR2|E_ADDR_ZERO, 44119304Speter "s", 44219304Speter "[line [,line]] ~ [cgr] [count] [#lp]", 44319304Speter "replace previous RE with previous replacement string,"}, 44419304Speter {NULL}, 44519304Speter}; 446