v_cmd.c revision 256281
1/*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10#include "config.h" 11 12#ifndef lint 13static const char sccsid[] = "$Id: v_cmd.c,v 10.9 1996/03/28 15:18:39 bostic Exp $"; 14#endif /* not lint */ 15 16#include <sys/types.h> 17#include <sys/queue.h> 18#include <sys/time.h> 19 20#include <bitstring.h> 21#include <limits.h> 22#include <stdio.h> 23 24#include "../common/common.h" 25#include "vi.h" 26 27/* 28 * This array maps keystrokes to vi command functions. It is known 29 * in ex/ex_usage.c that it takes four columns to name a vi character. 30 */ 31VIKEYS const vikeys [MAXVIKEY + 1] = { 32/* 000 NUL -- The code in vi.c expects key 0 to be undefined. */ 33 {NULL}, 34/* 001 ^A */ 35 {v_searchw, V_ABS|V_CNT|V_MOVE|V_KEYW|VM_CUTREQ|VM_RCM_SET, 36 "[count]^A", 37 "^A search forward for cursor word"}, 38/* 002 ^B */ 39 {v_pageup, V_CNT|VM_RCM_SET, 40 "[count]^B", 41 "^B scroll up by screens"}, 42/* 003 ^C */ 43 {NULL, 0, 44 "^C", 45 "^C interrupt an operation (e.g. read, write, search)"}, 46/* 004 ^D */ 47 {v_hpagedown, V_CNT|VM_RCM_SET, 48 "[count]^D", 49 "^D scroll down by half screens (setting count)"}, 50/* 005 ^E */ 51 {v_linedown, V_CNT, 52 "[count]^E", 53 "^E scroll down by lines"}, 54/* 006 ^F */ 55 {v_pagedown, V_CNT|VM_RCM_SET, 56 "[count]^F", 57 "^F scroll down by screens"}, 58/* 007 ^G */ 59 {v_status, 0, 60 "^G", 61 "^G file status"}, 62/* 010 ^H */ 63 {v_left, V_CNT|V_MOVE|VM_RCM_SET, 64 "[count]^H", 65 "^H move left by characters"}, 66/* 011 ^I */ 67 {NULL}, 68/* 012 ^J */ 69 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 70 "[count]^J", 71 "^J move down by lines"}, 72/* 013 ^K */ 73 {NULL}, 74/* 014 ^L */ 75 {v_redraw, 0, 76 "^L", 77 "^L redraw screen"}, 78/* 015 ^M */ 79 {v_cr, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 80 "[count]^M", 81 "^M move down by lines (to first non-blank)"}, 82/* 016 ^N */ 83 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 84 "[count]^N", 85 "^N move down by lines"}, 86/* 017 ^O */ 87 {NULL}, 88/* 020 ^P */ 89 {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 90 "[count]^P", 91 "^P move up by lines"}, 92/* 021 ^Q -- same as ^V if not used for hardware flow control. */ 93 {NULL}, 94/* 022 ^R */ 95 {v_redraw, 0, 96 "^R", 97 "^R redraw screen"}, 98/* 023 ^S -- not available, used for hardware flow control. */ 99 {NULL}, 100/* 024 ^T */ 101 {v_tagpop, V_ABS|VM_RCM_SET, 102 "^T", 103 "^T tag pop"}, 104/* 025 ^U */ 105 {v_hpageup, V_CNT|VM_RCM_SET, 106 "[count]^U", 107 "^U half page up (set count)"}, 108/* 026 ^V */ 109 {NULL, 0, 110 "^V", 111 "^V input a literal character"}, 112/* 027 ^W */ 113 {v_screen, 0, 114 "^W", 115 "^W move to next screen"}, 116/* 030 ^X */ 117 {NULL}, 118/* 031 ^Y */ 119 {v_lineup, V_CNT, 120 "[count]^Y", 121 "^Y page up by lines"}, 122/* 032 ^Z */ 123 {v_suspend, V_SECURE, 124 "^Z", 125 "^Z suspend editor"}, 126/* 033 ^[ */ 127 {NULL, 0, 128 "^[ <escape>", 129 "^[ <escape> exit input mode, cancel partial commands"}, 130/* 034 ^\ */ 131 {v_exmode, 0, 132 "^\\", 133 " ^\\ switch to ex mode"}, 134/* 035 ^] */ 135 {v_tagpush, V_ABS|V_KEYW|VM_RCM_SET, 136 "^]", 137 "^] tag push cursor word"}, 138/* 036 ^^ */ 139 {v_switch, 0, 140 "^^", 141 "^^ switch to previous file"}, 142/* 037 ^_ */ 143 {NULL}, 144/* 040 ' ' */ 145 {v_right, V_CNT|V_MOVE|VM_RCM_SET, 146 "[count]' '", 147 " <space> move right by columns"}, 148/* 041 ! */ 149 {v_filter, V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET, 150 "[count]![count]motion command(s)", 151 " ! filter through command(s) to motion"}, 152/* 042 " */ 153 {NULL}, 154/* 043 # */ 155 {v_increment, V_CHAR|V_CNT|V_DOT|VM_RCM_SET, 156 "[count]# +|-|#", 157 " # number increment/decrement"}, 158/* 044 $ */ 159 {v_dollar, V_CNT|V_MOVE|VM_RCM_SETLAST, 160 " [count]$", 161 " $ move to last column"}, 162/* 045 % */ 163 {v_match, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 164 "%", 165 " % move to match"}, 166/* 046 & */ 167 {v_again, 0, 168 "&", 169 " & repeat substitution"}, 170/* 047 ' */ 171 {v_fmark, V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET, 172 "'['a-z]", 173 " ' move to mark (to first non-blank)"}, 174/* 050 ( */ 175 {v_sentenceb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 176 "[count](", 177 " ( move back sentence"}, 178/* 051 ) */ 179 {v_sentencef, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 180 "[count])", 181 " ) move forward sentence"}, 182/* 052 * */ 183 {NULL}, 184/* 053 + */ 185 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 186 "[count]+", 187 " + move down by lines (to first non-blank)"}, 188/* 054 , */ 189 {v_chrrepeat, V_CNT|V_MOVE|VM_RCM_SET, 190 "[count],", 191 " , reverse last F, f, T or t search"}, 192/* 055 - */ 193 {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 194 "[count]-", 195 " - move up by lines (to first non-blank)"}, 196/* 056 . */ 197 {NULL, 0, 198 ".", 199 " . repeat the last command"}, 200/* 057 / */ 201 {v_searchf, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 202 "/RE[/ offset]", 203 " / search forward"}, 204/* 060 0 */ 205 {v_zero, V_MOVE|VM_RCM_SET, 206 "0", 207 " 0 move to first character"}, 208/* 061 1 */ 209 {NULL}, 210/* 062 2 */ 211 {NULL}, 212/* 063 3 */ 213 {NULL}, 214/* 064 4 */ 215 {NULL}, 216/* 065 5 */ 217 {NULL}, 218/* 066 6 */ 219 {NULL}, 220/* 067 7 */ 221 {NULL}, 222/* 070 8 */ 223 {NULL}, 224/* 071 9 */ 225 {NULL}, 226/* 072 : */ 227 {v_ex, 0, 228 ":command [| command] ...", 229 " : ex command"}, 230/* 073 ; */ 231 {v_chrepeat, V_CNT|V_MOVE|VM_RCM_SET, 232 "[count];", 233 " ; repeat last F, f, T or t search"}, 234/* 074 < */ 235 {v_shiftl, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 236 "[count]<[count]motion", 237 " < shift lines left to motion"}, 238/* 075 = */ 239 {NULL}, 240/* 076 > */ 241 {v_shiftr, V_CNT|V_DOT|V_MOTION|VM_RCM_SET, 242 "[count]>[count]motion", 243 " > shift lines right to motion"}, 244/* 077 ? */ 245 {v_searchb, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 246 "?RE[? offset]", 247 " ? search backward"}, 248/* 100 @ */ 249 {v_at, V_CNT|V_RBUF|VM_RCM_SET, 250 "@buffer", 251 " @ execute buffer"}, 252/* 101 A */ 253 {v_iA, V_CNT|V_DOT|VM_RCM_SET, 254 "[count]A", 255 " A append to the line"}, 256/* 102 B */ 257 {v_wordB, V_CNT|V_MOVE|VM_RCM_SET, 258 "[count]B", 259 " B move back bigword"}, 260/* 103 C */ 261 {NULL, 0, 262 "[buffer][count]C", 263 " C change to end-of-line"}, 264/* 104 D */ 265 {NULL, 0, 266 "[buffer]D", 267 " D delete to end-of-line"}, 268/* 105 E */ 269 {v_wordE, V_CNT|V_MOVE|VM_RCM_SET, 270 "[count]E", 271 " E move to end of bigword"}, 272/* 106 F */ 273 {v_chF, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 274 "[count]F character", 275 " F character in line backward search"}, 276/* 107 G */ 277 {v_lgoto, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB, 278 "[count]G", 279 " G move to line"}, 280/* 110 H */ 281 {v_home, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 282 "[count]H", 283 " H move to count lines from screen top"}, 284/* 111 I */ 285 {v_iI, V_CNT|V_DOT|VM_RCM_SET, 286 "[count]I", 287 " I insert before first nonblank"}, 288/* 112 J */ 289 {v_join, V_CNT|V_DOT|VM_RCM_SET, 290 "[count]J", 291 " J join lines"}, 292/* 113 K */ 293 {NULL}, 294/* 114 L */ 295 {v_bottom, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 296 "[count]L", 297 " L move to screen bottom"}, 298/* 115 M */ 299 {v_middle, V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB, 300 "M", 301 " M move to screen middle"}, 302/* 116 N */ 303 {v_searchN, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 304 "n", 305 " N reverse last search"}, 306/* 117 O */ 307 {v_iO, V_CNT|V_DOT|VM_RCM_SET, 308 "[count]O", 309 " O insert above line"}, 310/* 120 P */ 311 {v_Put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 312 "[buffer]P", 313 " P insert before cursor from buffer"}, 314/* 121 Q */ 315 {v_exmode, 0, 316 "Q", 317 " Q switch to ex mode"}, 318/* 122 R */ 319 {v_Replace, V_CNT|V_DOT|VM_RCM_SET, 320 "[count]R", 321 " R replace characters"}, 322/* 123 S */ 323 {NULL, 0, 324 "[buffer][count]S", 325 " S substitute for the line(s)"}, 326/* 124 T */ 327 {v_chT, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 328 "[count]T character", 329 " T before character in line backward search"}, 330/* 125 U */ 331 {v_Undo, VM_RCM_SET, 332 "U", 333 " U Restore the current line"}, 334/* 126 V */ 335 {NULL}, 336/* 127 W */ 337 {v_wordW, V_CNT|V_MOVE|VM_RCM_SET, 338 "[count]W", 339 " W move to next bigword"}, 340/* 130 X */ 341 {v_Xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 342 "[buffer][count]X", 343 " X delete character before cursor"}, 344/* 131 Y */ 345 {NULL, 0, 346 "[buffer][count]Y", 347 " Y copy line"}, 348/* 132 Z */ 349 {v_zexit, 0, 350 "ZZ", 351 "ZZ save file and exit"}, 352/* 133 [ */ 353 {v_sectionb, V_ABS|V_CNT|V_MOVE|VM_RCM_SET, 354 "[[", 355 "[[ move back section"}, 356/* 134 \ */ 357 {NULL}, 358/* 135 ] */ 359 {v_sectionf, V_ABS|V_CNT|V_MOVE|VM_RCM_SET, 360 "]]", 361 "]] move forward section"}, 362/* 136 ^ */ 363 /* 364 * DON'T set the VM_RCM_SETFNB flag, the function has to do the work 365 * anyway, in case it's a motion component. DO set VM_RCM_SET, so 366 * that any motion that's part of a command is preserved. 367 */ 368 {v_first, V_CNT|V_MOVE|VM_RCM_SET, 369 "^", 370 " ^ move to first non-blank"}, 371/* 137 _ */ 372 /* 373 * Needs both to set the VM_RCM_SETFNB flag, and to do the work 374 * in the function, in case it's a delete. 375 */ 376 {v_cfirst, V_CNT|V_MOVE|VM_RCM_SETFNB, 377 "_", 378 " _ move to first non-blank"}, 379/* 140 ` */ 380 {v_bmark, V_ABS_C|V_CHAR|V_MOVE|VM_CUTREQ|VM_RCM_SET, 381 "`[`a-z]", 382 " ` move to mark"}, 383/* 141 a */ 384 {v_ia, V_CNT|V_DOT|VM_RCM_SET, 385 "[count]a", 386 " a append after cursor"}, 387/* 142 b */ 388 {v_wordb, V_CNT|V_MOVE|VM_RCM_SET, 389 "[count]b", 390 " b move back word"}, 391/* 143 c */ 392 {v_change, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 393 "[buffer][count]c[count]motion", 394 " c change to motion"}, 395/* 144 d */ 396 {v_delete, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 397 "[buffer][count]d[count]motion", 398 " d delete to motion"}, 399/* 145 e */ 400 {v_worde, V_CNT|V_MOVE|VM_RCM_SET, 401 "[count]e", 402 " e move to end of word"}, 403/* 146 f */ 404 {v_chf, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 405 "[count]f character", 406 " f character in line forward search"}, 407/* 147 g */ 408 {NULL}, 409/* 150 h */ 410 {v_left, V_CNT|V_MOVE|VM_RCM_SET, 411 "[count]h", 412 " h move left by columns"}, 413/* 151 i */ 414 {v_ii, V_CNT|V_DOT|VM_RCM_SET, 415 "[count]i", 416 " i insert before cursor"}, 417/* 152 j */ 418 {v_down, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 419 "[count]j", 420 " j move down by lines"}, 421/* 153 k */ 422 {v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM, 423 "[count]k", 424 " k move up by lines"}, 425/* 154 l */ 426 {v_right, V_CNT|V_MOVE|VM_RCM_SET, 427 "[count]l", 428 " l move right by columns"}, 429/* 155 m */ 430 {v_mark, V_CHAR, 431 "m[a-z]", 432 " m set mark"}, 433/* 156 n */ 434 {v_searchn, V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET, 435 "n", 436 " n repeat last search"}, 437/* 157 o */ 438 {v_io, V_CNT|V_DOT|VM_RCM_SET, 439 "[count]o", 440 " o append after line"}, 441/* 160 p */ 442 {v_put, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 443 "[buffer]p", 444 " p insert after cursor from buffer"}, 445/* 161 q */ 446 {NULL}, 447/* 162 r */ 448 {v_replace, V_CNT|V_DOT|VM_RCM_SET, 449 "[count]r character", 450 " r replace character"}, 451/* 163 s */ 452 {v_subst, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 453 "[buffer][count]s", 454 " s substitute character"}, 455/* 164 t */ 456 {v_cht, V_CHAR|V_CNT|V_MOVE|VM_RCM_SET, 457 "[count]t character", 458 " t before character in line forward search"}, 459/* 165 u */ 460 /* 461 * DON'T set the V_DOT flag, it' more complicated than that. 462 * See vi/vi.c for details. 463 */ 464 {v_undo, VM_RCM_SET, 465 "u", 466 " u undo last change"}, 467/* 166 v */ 468 {NULL}, 469/* 167 w */ 470 {v_wordw, V_CNT|V_MOVE|VM_RCM_SET, 471 "[count]w", 472 " w move to next word"}, 473/* 170 x */ 474 {v_xchar, V_CNT|V_DOT|V_OBUF|VM_RCM_SET, 475 "[buffer][count]x", 476 " x delete character"}, 477/* 171 y */ 478 {v_yank, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET, 479 "[buffer][count]y[count]motion", 480 " y copy text to motion into a cut buffer"}, 481/* 172 z */ 482 /* 483 * DON'T set the V_CHAR flag, the char isn't required, 484 * so it's handled specially in getcmd(). 485 */ 486 {v_z, V_ABS_L|V_CNT|VM_RCM_SETFNB, 487 "[line]z[window_size][-|.|+|^|<CR>]", 488 " z reposition the screen"}, 489/* 173 { */ 490 {v_paragraphb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 491 "[count]{", 492 " { move back paragraph"}, 493/* 174 | */ 494 {v_ncol, V_CNT|V_MOVE|VM_RCM_SET, 495 "[count]|", 496 " | move to column"}, 497/* 175 } */ 498 {v_paragraphf, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET, 499 "[count]}", 500 " } move forward paragraph"}, 501/* 176 ~ */ 502 {v_ulcase, V_CNT|V_DOT|VM_RCM_SET, 503 "[count]~", 504 " ~ reverse case"}, 505}; 506