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