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