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 13 static 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 */ 31 VIKEYS 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