v_cmd.c revision 19304
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[] = "@(#)v_cmd.c 10.9 (Berkeley) 3/28/96"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <limits.h> 2219304Speter#include <stdio.h> 2319304Speter 2419304Speter#include "../common/common.h" 2519304Speter#include "vi.h" 2619304Speter 2719304Speter/* 2819304Speter * This array maps keystrokes to vi command functions. It is known 2919304Speter * in ex/ex_usage.c that it takes four columns to name a vi character. 3019304Speter */ 3119304SpeterVIKEYS const vikeys [MAXVIKEY + 1] = { 3219304Speter/* 000 NUL -- The code in vi.c expects key 0 to be undefined. */ 3319304Speter {NULL}, 3419304Speter/* 001 ^A */ 3519304Speter {v_searchw, V_ABS|V_CNT|V_MOVE|V_KEYW|VM_CUTREQ|VM_RCM_SET, 3619304Speter "[count]^A", 3719304Speter "^A search forward for cursor word"}, 3819304Speter/* 002 ^B */ 3919304Speter {v_pageup, V_CNT|VM_RCM_SET, 4019304Speter "[count]^B", 4119304Speter "^B scroll up by screens"}, 4219304Speter/* 003 ^C */ 4319304Speter {NULL, 0, 4419304Speter "^C", 4519304Speter "^C interrupt an operation (e.g. read, write, search)"}, 4619304Speter/* 004 ^D */ 4719304Speter {v_hpagedown, V_CNT|VM_RCM_SET, 4819304Speter "[count]^D", 4919304Speter "^D scroll down by half screens (setting count)"}, 5019304Speter/* 005 ^E */ 5119304Speter {v_linedown, V_CNT, 5219304Speter "[count]^E", 5319304Speter "^E scroll down by lines"}, 5419304Speter/* 006 ^F */ 5519304Speter {v_pagedown, V_CNT|VM_RCM_SET, 5619304Speter "[count]^F", 5719304Speter "^F scroll down by screens"}, 5819304Speter/* 007 ^G */ 5919304Speter {v_status, 0, 6019304Speter "^G", 6119304Speter "^G file status"}, 6219304Speter/* 010 ^H */ 6319304Speter {v_left, V_CNT|V_MOVE|VM_RCM_SET, 6419304Speter "[count]^H", 6519304Speter "^H move left by characters"}, 6619304Speter/* 011 ^I */ 6719304Speter {NULL}, 6819304Speter/* 012 ^J */ 6919304Speter {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 7019304Speter "[count]^J", 7119304Speter "^J move down by lines"}, 7219304Speter/* 013 ^K */ 7319304Speter {NULL}, 7419304Speter/* 014 ^L */ 7519304Speter {v_redraw, 0, 7619304Speter "^L", 7719304Speter "^L redraw screen"}, 7819304Speter/* 015 ^M */ 7919304Speter {v_cr, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 8019304Speter "[count]^M", 8119304Speter "^M move down by lines (to first non-blank)"}, 8219304Speter/* 016 ^N */ 8319304Speter {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 8419304Speter "[count]^N", 8519304Speter "^N move down by lines"}, 8619304Speter/* 017 ^O */ 8719304Speter {NULL}, 8819304Speter/* 020 ^P */ 8919304Speter {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 9019304Speter "[count]^P", 9119304Speter "^P move up by lines"}, 9219304Speter/* 021 ^Q -- same as ^V if not used for hardware flow control. */ 9319304Speter {NULL}, 9419304Speter/* 022 ^R */ 9519304Speter {v_redraw, 0, 9619304Speter "^R", 9719304Speter "^R redraw screen"}, 9819304Speter/* 023 ^S -- not available, used for hardware flow control. */ 9919304Speter {NULL}, 10019304Speter/* 024 ^T */ 10119304Speter {v_tagpop, V_ABS|VM_RCM_SET, 10219304Speter "^T", 10319304Speter "^T tag pop"}, 10419304Speter/* 025 ^U */ 10519304Speter {v_hpageup, V_CNT|VM_RCM_SET, 10619304Speter "[count]^U", 10719304Speter "^U half page up (set count)"}, 10819304Speter/* 026 ^V */ 10919304Speter {NULL, 0, 11019304Speter "^V", 11119304Speter "^V input a literal character"}, 11219304Speter/* 027 ^W */ 11319304Speter {v_screen, 0, 11419304Speter "^W", 11519304Speter "^W move to next screen"}, 11619304Speter/* 030 ^X */ 11719304Speter {NULL}, 11819304Speter/* 031 ^Y */ 11919304Speter {v_lineup, V_CNT, 12019304Speter "[count]^Y", 12119304Speter "^Y page up by lines"}, 12219304Speter/* 032 ^Z */ 12319304Speter {v_suspend, V_SECURE, 12419304Speter "^Z", 12519304Speter "^Z suspend editor"}, 12619304Speter/* 033 ^[ */ 12719304Speter {NULL, 0, 12819304Speter "^[ <escape>", 12919304Speter "^[ <escape> exit input mode, cancel partial commands"}, 13019304Speter/* 034 ^\ */ 13119304Speter {v_exmode, 0, 13219304Speter "^\\", 13319304Speter " ^\\ switch to ex mode"}, 13419304Speter/* 035 ^] */ 13519304Speter {v_tagpush, V_ABS|V_KEYW|VM_RCM_SET, 13619304Speter "^]", 13719304Speter "^] tag push cursor word"}, 13819304Speter/* 036 ^^ */ 13919304Speter {v_switch, 0, 14019304Speter "^^", 14119304Speter "^^ switch to previous file"}, 14219304Speter/* 037 ^_ */ 14319304Speter {NULL}, 14419304Speter/* 040 ' ' */ 14519304Speter {v_right, V_CNT|V_MOVE|VM_RCM_SET, 14619304Speter "[count]' '", 14719304Speter " <space> move right by columns"}, 14819304Speter/* 041 ! */ 14919304Speter {v_filter, V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET, 15019304Speter "[count]![count]motion command(s)", 15119304Speter " ! filter through command(s) to motion"}, 15219304Speter/* 042 " */ 15319304Speter {NULL}, 15419304Speter/* 043 # */ 15519304Speter {v_increment, V_CHAR|V_CNT|V_DOT|VM_RCM_SET, 15619304Speter "[count]# +|-|#", 15719304Speter " # number increment/decrement"}, 15819304Speter/* 044 $ */ 15919304Speter {v_dollar, V_CNT|V_MOVE|VM_RCM_SETLAST, 16019304Speter " [count]$", 16119304Speter " $ move to last column"}, 16219304Speter/* 045 % */ 16319304Speter {v_match, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 16419304Speter "%", 16519304Speter " % move to match"}, 16619304Speter/* 046 & */ 16719304Speter {v_again, 0, 16819304Speter "&", 16919304Speter " & repeat substitution"}, 17019304Speter/* 047 ' */ 17119304Speter {v_fmark, V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET, 17219304Speter "'['a-z]", 17319304Speter " ' move to mark (to first non-blank)"}, 17419304Speter/* 050 ( */ 17519304Speter {v_sentenceb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 17619304Speter "[count](", 17719304Speter " ( move back sentence"}, 17819304Speter/* 051 ) */ 17919304Speter {v_sentencef, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 18019304Speter "[count])", 18119304Speter " ) move forward sentence"}, 18219304Speter/* 052 * */ 18319304Speter {NULL}, 18419304Speter/* 053 + */ 18519304Speter {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 18619304Speter "[count]+", 18719304Speter " + move down by lines (to first non-blank)"}, 18819304Speter/* 054 , */ 18919304Speter {v_chrrepeat, V_CNT|V_MOVE|VM_RCM_SET, 19019304Speter "[count],", 19119304Speter " , reverse last F, f, T or t search"}, 19219304Speter/* 055 - */ 19319304Speter {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 19419304Speter "[count]-", 19519304Speter " - move up by lines (to first non-blank)"}, 19619304Speter/* 056 . */ 19719304Speter {NULL, 0, 19819304Speter ".", 19919304Speter " . repeat the last command"}, 20019304Speter/* 057 / */ 20119304Speter {v_searchf, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 20219304Speter "/RE[/ offset]", 20319304Speter " / search forward"}, 20419304Speter/* 060 0 */ 20519304Speter {v_zero, V_MOVE|VM_RCM_SET, 20619304Speter "0", 20719304Speter " 0 move to first character"}, 20819304Speter/* 061 1 */ 20919304Speter {NULL}, 21019304Speter/* 062 2 */ 21119304Speter {NULL}, 21219304Speter/* 063 3 */ 21319304Speter {NULL}, 21419304Speter/* 064 4 */ 21519304Speter {NULL}, 21619304Speter/* 065 5 */ 21719304Speter {NULL}, 21819304Speter/* 066 6 */ 21919304Speter {NULL}, 22019304Speter/* 067 7 */ 22119304Speter {NULL}, 22219304Speter/* 070 8 */ 22319304Speter {NULL}, 22419304Speter/* 071 9 */ 22519304Speter {NULL}, 22619304Speter/* 072 : */ 22719304Speter {v_ex, 0, 22819304Speter ":command [| command] ...", 22919304Speter " : ex command"}, 23019304Speter/* 073 ; */ 23119304Speter {v_chrepeat, V_CNT|V_MOVE|VM_RCM_SET, 23219304Speter "[count];", 23319304Speter " ; repeat last F, f, T or t search"}, 23419304Speter/* 074 < */ 23519304Speter {v_shiftl, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 23619304Speter "[count]<[count]motion", 23719304Speter " < shift lines left to motion"}, 23819304Speter/* 075 = */ 23919304Speter {NULL}, 24019304Speter/* 076 > */ 24119304Speter {v_shiftr, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 24219304Speter "[count]>[count]motion", 24319304Speter " > shift lines right to motion"}, 24419304Speter/* 077 ? */ 24519304Speter {v_searchb, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 24619304Speter "?RE[? offset]", 24719304Speter " ? search backward"}, 24819304Speter/* 100 @ */ 24919304Speter {v_at, V_CNT|V_RBUF|VM_RCM_SET, 25019304Speter "@buffer", 25119304Speter " @ execute buffer"}, 25219304Speter/* 101 A */ 25319304Speter {v_iA, V_CNT|V_DOT|VM_RCM_SET, 25419304Speter "[count]A", 25519304Speter " A append to the line"}, 25619304Speter/* 102 B */ 25719304Speter {v_wordB, V_CNT|V_MOVE|VM_RCM_SET, 25819304Speter "[count]B", 25919304Speter " B move back bigword"}, 26019304Speter/* 103 C */ 26119304Speter {NULL, 0, 26219304Speter "[buffer][count]C", 26319304Speter " C change to end-of-line"}, 26419304Speter/* 104 D */ 26519304Speter {NULL, 0, 26619304Speter "[buffer]D", 26719304Speter " D delete to end-of-line"}, 26819304Speter/* 105 E */ 26919304Speter {v_wordE, V_CNT|V_MOVE|VM_RCM_SET, 27019304Speter "[count]E", 27119304Speter " E move to end of bigword"}, 27219304Speter/* 106 F */ 27319304Speter {v_chF, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 27419304Speter "[count]F character", 27519304Speter " F character in line backward search"}, 27619304Speter/* 107 G */ 27719304Speter {v_lgoto, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 27819304Speter "[count]G", 27919304Speter " G move to line"}, 28019304Speter/* 110 H */ 28119304Speter {v_home, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 28219304Speter "[count]H", 28319304Speter " H move to count lines from screen top"}, 28419304Speter/* 111 I */ 28519304Speter {v_iI, V_CNT|V_DOT|VM_RCM_SET, 28619304Speter "[count]I", 28719304Speter " I insert before first nonblank"}, 28819304Speter/* 112 J */ 28919304Speter {v_join, V_CNT|V_DOT|VM_RCM_SET, 29019304Speter "[count]J", 29119304Speter " J join lines"}, 29219304Speter/* 113 K */ 29319304Speter {NULL}, 29419304Speter/* 114 L */ 29519304Speter {v_bottom, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 29619304Speter "[count]L", 29719304Speter " L move to screen bottom"}, 29819304Speter/* 115 M */ 29919304Speter {v_middle, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 30019304Speter "M", 30119304Speter " M move to screen middle"}, 30219304Speter/* 116 N */ 30319304Speter {v_searchN, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 30419304Speter "n", 30519304Speter " N reverse last search"}, 30619304Speter/* 117 O */ 30719304Speter {v_iO, V_CNT|V_DOT|VM_RCM_SET, 30819304Speter "[count]O", 30919304Speter " O insert above line"}, 31019304Speter/* 120 P */ 31119304Speter {v_Put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 31219304Speter "[buffer]P", 31319304Speter " P insert before cursor from buffer"}, 31419304Speter/* 121 Q */ 31519304Speter {v_exmode, 0, 31619304Speter "Q", 31719304Speter " Q switch to ex mode"}, 31819304Speter/* 122 R */ 31919304Speter {v_Replace, V_CNT|V_DOT|VM_RCM_SET, 32019304Speter "[count]R", 32119304Speter " R replace characters"}, 32219304Speter/* 123 S */ 32319304Speter {NULL, 0, 32419304Speter "[buffer][count]S", 32519304Speter " S substitute for the line(s)"}, 32619304Speter/* 124 T */ 32719304Speter {v_chT, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 32819304Speter "[count]T character", 32919304Speter " T before character in line backward search"}, 33019304Speter/* 125 U */ 33119304Speter {v_Undo, VM_RCM_SET, 33219304Speter "U", 33319304Speter " U Restore the current line"}, 33419304Speter/* 126 V */ 33519304Speter {NULL}, 33619304Speter/* 127 W */ 33719304Speter {v_wordW, V_CNT|V_MOVE|VM_RCM_SET, 33819304Speter "[count]W", 33919304Speter " W move to next bigword"}, 34019304Speter/* 130 X */ 34119304Speter {v_Xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 34219304Speter "[buffer][count]X", 34319304Speter " X delete character before cursor"}, 34419304Speter/* 131 Y */ 34519304Speter {NULL, 0, 34619304Speter "[buffer][count]Y", 34719304Speter " Y copy line"}, 34819304Speter/* 132 Z */ 34919304Speter {v_zexit, 0, 35019304Speter "ZZ", 35119304Speter "ZZ save file and exit"}, 35219304Speter/* 133 [ */ 35319304Speter {v_sectionb, V_ABS|V_CNT|V_MOVE|VM_RCM_SET, 35419304Speter "[[", 35519304Speter "[[ move back section"}, 35619304Speter/* 134 \ */ 35719304Speter {NULL}, 35819304Speter/* 135 ] */ 35919304Speter {v_sectionf, V_ABS|V_CNT|V_MOVE|VM_RCM_SET, 36019304Speter "]]", 36119304Speter "]] move forward section"}, 36219304Speter/* 136 ^ */ 36319304Speter /* 36419304Speter * DON'T set the VM_RCM_SETFNB flag, the function has to do the work 36519304Speter * anyway, in case it's a motion component. DO set VM_RCM_SET, so 36619304Speter * that any motion that's part of a command is preserved. 36719304Speter */ 36819304Speter {v_first, V_CNT|V_MOVE|VM_RCM_SET, 36919304Speter "^", 37019304Speter " ^ move to first non-blank"}, 37119304Speter/* 137 _ */ 37219304Speter /* 37319304Speter * Needs both to set the VM_RCM_SETFNB flag, and to do the work 37419304Speter * in the function, in case it's a delete. 37519304Speter */ 37619304Speter {v_cfirst, V_CNT|V_MOVE|VM_RCM_SETFNB, 37719304Speter "_", 37819304Speter " _ move to first non-blank"}, 37919304Speter/* 140 ` */ 38019304Speter {v_bmark, V_ABS_C|V_CHAR|V_MOVE|VM_CUTREQ|VM_RCM_SET, 38119304Speter "`[`a-z]", 38219304Speter " ` move to mark"}, 38319304Speter/* 141 a */ 38419304Speter {v_ia, V_CNT|V_DOT|VM_RCM_SET, 38519304Speter "[count]a", 38619304Speter " a append after cursor"}, 38719304Speter/* 142 b */ 38819304Speter {v_wordb, V_CNT|V_MOVE|VM_RCM_SET, 38919304Speter "[count]b", 39019304Speter " b move back word"}, 39119304Speter/* 143 c */ 39219304Speter {v_change, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 39319304Speter "[buffer][count]c[count]motion", 39419304Speter " c change to motion"}, 39519304Speter/* 144 d */ 39619304Speter {v_delete, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 39719304Speter "[buffer][count]d[count]motion", 39819304Speter " d delete to motion"}, 39919304Speter/* 145 e */ 40019304Speter {v_worde, V_CNT|V_MOVE|VM_RCM_SET, 40119304Speter "[count]e", 40219304Speter " e move to end of word"}, 40319304Speter/* 146 f */ 40419304Speter {v_chf, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 40519304Speter "[count]f character", 40619304Speter " f character in line forward search"}, 40719304Speter/* 147 g */ 40819304Speter {NULL}, 40919304Speter/* 150 h */ 41019304Speter {v_left, V_CNT|V_MOVE|VM_RCM_SET, 41119304Speter "[count]h", 41219304Speter " h move left by columns"}, 41319304Speter/* 151 i */ 41419304Speter {v_ii, V_CNT|V_DOT|VM_RCM_SET, 41519304Speter "[count]i", 41619304Speter " i insert before cursor"}, 41719304Speter/* 152 j */ 41819304Speter {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 41919304Speter "[count]j", 42019304Speter " j move down by lines"}, 42119304Speter/* 153 k */ 42219304Speter {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 42319304Speter "[count]k", 42419304Speter " k move up by lines"}, 42519304Speter/* 154 l */ 42619304Speter {v_right, V_CNT|V_MOVE|VM_RCM_SET, 42719304Speter "[count]l", 42819304Speter " l move right by columns"}, 42919304Speter/* 155 m */ 43019304Speter {v_mark, V_CHAR, 43119304Speter "m[a-z]", 43219304Speter " m set mark"}, 43319304Speter/* 156 n */ 43419304Speter {v_searchn, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 43519304Speter "n", 43619304Speter " n repeat last search"}, 43719304Speter/* 157 o */ 43819304Speter {v_io, V_CNT|V_DOT|VM_RCM_SET, 43919304Speter "[count]o", 44019304Speter " o append after line"}, 44119304Speter/* 160 p */ 44219304Speter {v_put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 44319304Speter "[buffer]p", 44419304Speter " p insert after cursor from buffer"}, 44519304Speter/* 161 q */ 44619304Speter {NULL}, 44719304Speter/* 162 r */ 44819304Speter {v_replace, V_CNT|V_DOT|VM_RCM_SET, 44919304Speter "[count]r character", 45019304Speter " r replace character"}, 45119304Speter/* 163 s */ 45219304Speter {v_subst, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 45319304Speter "[buffer][count]s", 45419304Speter " s substitute character"}, 45519304Speter/* 164 t */ 45619304Speter {v_cht, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 45719304Speter "[count]t character", 45819304Speter " t before character in line forward search"}, 45919304Speter/* 165 u */ 46019304Speter /* 46119304Speter * DON'T set the V_DOT flag, it' more complicated than that. 46219304Speter * See vi/vi.c for details. 46319304Speter */ 46419304Speter {v_undo, VM_RCM_SET, 46519304Speter "u", 46619304Speter " u undo last change"}, 46719304Speter/* 166 v */ 46819304Speter {NULL}, 46919304Speter/* 167 w */ 47019304Speter {v_wordw, V_CNT|V_MOVE|VM_RCM_SET, 47119304Speter "[count]w", 47219304Speter " w move to next word"}, 47319304Speter/* 170 x */ 47419304Speter {v_xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 47519304Speter "[buffer][count]x", 47619304Speter " x delete character"}, 47719304Speter/* 171 y */ 47819304Speter {v_yank, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 47919304Speter "[buffer][count]y[count]motion", 48019304Speter " y copy text to motion into a cut buffer"}, 48119304Speter/* 172 z */ 48219304Speter /* 48319304Speter * DON'T set the V_CHAR flag, the char isn't required, 48419304Speter * so it's handled specially in getcmd(). 48519304Speter */ 48619304Speter {v_z, V_ABS_L|V_CNT|VM_RCM_SETFNB, 48719304Speter "[line]z[window_size][-|.|+|^|<CR>]", 48819304Speter " z reposition the screen"}, 48919304Speter/* 173 { */ 49019304Speter {v_paragraphb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 49119304Speter "[count]{", 49219304Speter " { move back paragraph"}, 49319304Speter/* 174 | */ 49419304Speter {v_ncol, V_CNT|V_MOVE|VM_RCM_SET, 49519304Speter "[count]|", 49619304Speter " | move to column"}, 49719304Speter/* 175 } */ 49819304Speter {v_paragraphf, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 49919304Speter "[count]}", 50019304Speter " } move forward paragraph"}, 50119304Speter/* 176 ~ */ 50219304Speter {v_ulcase, V_CNT|V_DOT|VM_RCM_SET, 50319304Speter "[count]~", 50419304Speter " ~ reverse case"}, 50519304Speter}; 506