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