1 /* 2 * Copyright (c) 2002-2012, the original author or authors. 3 * 4 * This software is distributable under the BSD license. See the terms of the 5 * BSD license in the documentation provided with this software. 6 * 7 * http://www.opensource.org/licenses/bsd-license.php 8 */ 9 package jdk.internal.jline.console; 10 11 import java.util.HashMap; 12 import java.util.Map; 13 14 /** 15 * The KeyMap class contains all bindings from keys to operations. 16 * 17 * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a> 18 * @since 2.6 19 */ 20 public class KeyMap { 21 22 public static final String VI_MOVE = "vi-move"; 23 public static final String VI_INSERT = "vi-insert"; 24 public static final String EMACS = "emacs"; 25 public static final String EMACS_STANDARD = "emacs-standard"; 26 public static final String EMACS_CTLX = "emacs-ctlx"; 27 public static final String EMACS_META = "emacs-meta"; 28 29 private static final int KEYMAP_LENGTH = 256; 30 31 private static final Object NULL_FUNCTION = new Object(); 32 33 private Object[] mapping = new Object[KEYMAP_LENGTH]; 34 private Object anotherKey = null; 35 private String name; 36 private boolean isViKeyMap; 37 38 public KeyMap(String name, boolean isViKeyMap) { 39 this(name, new Object[KEYMAP_LENGTH], isViKeyMap); 40 } 41 42 protected KeyMap(String name, Object[] mapping, boolean isViKeyMap) { 43 this.mapping = mapping; 44 this.name = name; 45 this.isViKeyMap = isViKeyMap; 46 } 47 48 public boolean isViKeyMap() { 49 return isViKeyMap; 50 } 51 52 public String getName() { 53 return name; 54 } 55 56 public Object getAnotherKey() { 57 return anotherKey; 58 } 59 60 public void from(KeyMap other) { 61 this.mapping = other.mapping; 62 this.anotherKey = other.anotherKey; 63 } 64 65 public Object getBound( CharSequence keySeq ) { 66 if (keySeq != null && keySeq.length() > 0) { 67 KeyMap map = this; 68 for (int i = 0; i < keySeq.length(); i++) { 69 char c = keySeq.charAt(i); 70 if (c > 255) { 71 return Operation.SELF_INSERT; 72 } 73 if (map.mapping[c] instanceof KeyMap) { 74 if (i == keySeq.length() - 1) { 75 return map.mapping[c]; 76 } else { 77 map = (KeyMap) map.mapping[c]; 78 } 79 } else { 80 return map.mapping[c]; 81 } 82 } 83 } 84 return null; 85 } 86 87 public void bindIfNotBound( CharSequence keySeq, Object function ) { 88 89 bind (this, keySeq, function, true); 90 } 91 92 public void bind( CharSequence keySeq, Object function ) { 93 94 bind (this, keySeq, function, false); 95 } 96 97 private static void bind( KeyMap map, CharSequence keySeq, Object function ) { 98 99 bind (map, keySeq, function, false); 100 } 101 102 private static void bind( KeyMap map, CharSequence keySeq, Object function, 103 boolean onlyIfNotBound ) { 104 105 if (keySeq != null && keySeq.length() > 0) { 106 for (int i = 0; i < keySeq.length(); i++) { 107 char c = keySeq.charAt(i); 108 if (c >= map.mapping.length) { 109 return; 110 } 111 if (i < keySeq.length() - 1) { 112 if (!(map.mapping[c] instanceof KeyMap)) { 113 KeyMap m = new KeyMap("anonymous", false); 114 if (map.mapping[c] != Operation.DO_LOWERCASE_VERSION) { 115 m.anotherKey = map.mapping[c]; 116 } 117 map.mapping[c] = m; 118 } 119 map = (KeyMap) map.mapping[c]; 120 } else { 121 if (function == null) { 122 function = NULL_FUNCTION; 123 } 124 if (map.mapping[c] instanceof KeyMap) { 125 map.anotherKey = function; 126 } else { 127 Object op = map.mapping[c]; 128 if (onlyIfNotBound == false 129 || op == null 130 || op == Operation.DO_LOWERCASE_VERSION 131 || op == Operation.VI_MOVEMENT_MODE ) { 132 133 } 134 135 map.mapping[c] = function; 136 } 137 } 138 } 139 } 140 } 141 142 public void setBlinkMatchingParen(boolean on) { 143 if (on) { 144 bind( "}", Operation.INSERT_CLOSE_CURLY ); 145 bind( ")", Operation.INSERT_CLOSE_PAREN ); 146 bind( "]", Operation.INSERT_CLOSE_SQUARE ); 147 } 148 } 149 150 private static void bindArrowKeys(KeyMap map) { 151 152 // MS-DOS 153 bind( map, "\033[0A", Operation.PREVIOUS_HISTORY ); 154 bind( map, "\033[0B", Operation.BACKWARD_CHAR ); 155 bind( map, "\033[0C", Operation.FORWARD_CHAR ); 156 bind( map, "\033[0D", Operation.NEXT_HISTORY ); 157 158 // Windows 159 bind( map, "\340\000", Operation.KILL_WHOLE_LINE ); 160 bind( map, "\340\107", Operation.BEGINNING_OF_LINE ); 161 bind( map, "\340\110", Operation.PREVIOUS_HISTORY ); 162 bind( map, "\340\111", Operation.BEGINNING_OF_HISTORY ); 163 bind( map, "\340\113", Operation.BACKWARD_CHAR ); 164 bind( map, "\340\115", Operation.FORWARD_CHAR ); 165 bind( map, "\340\117", Operation.END_OF_LINE ); 166 bind( map, "\340\120", Operation.NEXT_HISTORY ); 167 bind( map, "\340\121", Operation.END_OF_HISTORY ); 168 bind( map, "\340\122", Operation.OVERWRITE_MODE ); 169 bind( map, "\340\123", Operation.DELETE_CHAR ); 170 171 bind( map, "\000\107", Operation.BEGINNING_OF_LINE ); 172 bind( map, "\000\110", Operation.PREVIOUS_HISTORY ); 173 bind( map, "\000\111", Operation.BEGINNING_OF_HISTORY ); 174 bind( map, "\000\110", Operation.PREVIOUS_HISTORY ); 175 bind( map, "\000\113", Operation.BACKWARD_CHAR ); 176 bind( map, "\000\115", Operation.FORWARD_CHAR ); 177 bind( map, "\000\117", Operation.END_OF_LINE ); 178 bind( map, "\000\120", Operation.NEXT_HISTORY ); 179 bind( map, "\000\121", Operation.END_OF_HISTORY ); 180 bind( map, "\000\122", Operation.OVERWRITE_MODE ); 181 bind( map, "\000\123", Operation.DELETE_CHAR ); 182 183 bind( map, "\033[A", Operation.PREVIOUS_HISTORY ); 184 bind( map, "\033[B", Operation.NEXT_HISTORY ); 185 bind( map, "\033[C", Operation.FORWARD_CHAR ); 186 bind( map, "\033[D", Operation.BACKWARD_CHAR ); 187 bind( map, "\033[H", Operation.BEGINNING_OF_LINE ); 188 bind( map, "\033[F", Operation.END_OF_LINE ); 189 190 bind( map, "\033OA", Operation.PREVIOUS_HISTORY ); 191 bind( map, "\033OB", Operation.NEXT_HISTORY ); 192 bind( map, "\033OC", Operation.FORWARD_CHAR ); 193 bind( map, "\033OD", Operation.BACKWARD_CHAR ); 194 bind( map, "\033OH", Operation.BEGINNING_OF_LINE ); 195 bind( map, "\033OF", Operation.END_OF_LINE ); 196 197 bind( map, "\033[1~", Operation.BEGINNING_OF_LINE); 198 bind( map, "\033[4~", Operation.END_OF_LINE); 199 bind( map, "\033[3~", Operation.DELETE_CHAR); 200 201 // MINGW32 202 bind( map, "\0340H", Operation.PREVIOUS_HISTORY ); 203 bind( map, "\0340P", Operation.NEXT_HISTORY ); 204 bind( map, "\0340M", Operation.FORWARD_CHAR ); 205 bind( map, "\0340K", Operation.BACKWARD_CHAR ); 206 } 207 208 // public boolean isConvertMetaCharsToAscii() { 209 // return convertMetaCharsToAscii; 210 // } 211 212 // public void setConvertMetaCharsToAscii(boolean convertMetaCharsToAscii) { 213 // this.convertMetaCharsToAscii = convertMetaCharsToAscii; 214 // } 215 216 public static boolean isMeta( char c ) { 217 return c > 0x7f && c <= 0xff; 218 } 219 220 public static char unMeta( char c ) { 221 return (char) (c & 0x7F); 222 } 223 224 public static char meta( char c ) { 225 return (char) (c | 0x80); 226 } 227 228 public static Map<String, KeyMap> keyMaps() { 229 Map<String, KeyMap> keyMaps = new HashMap<String, KeyMap>(); 230 231 KeyMap emacs = emacs(); 232 bindArrowKeys(emacs); 233 keyMaps.put(EMACS, emacs); 234 keyMaps.put(EMACS_STANDARD, emacs); 235 keyMaps.put(EMACS_CTLX, (KeyMap) emacs.getBound("\u0018")); 236 keyMaps.put(EMACS_META, (KeyMap) emacs.getBound("\u001b")); 237 238 KeyMap viMov = viMovement(); 239 bindArrowKeys(viMov); 240 keyMaps.put(VI_MOVE, viMov); 241 keyMaps.put("vi-command", viMov); 242 243 KeyMap viIns = viInsertion(); 244 bindArrowKeys(viIns); 245 keyMaps.put(VI_INSERT, viIns); 246 keyMaps.put("vi", viIns); 247 248 return keyMaps; 249 } 250 251 public static KeyMap emacs() { 252 Object[] map = new Object[KEYMAP_LENGTH]; 253 Object[] ctrl = new Object[] { 254 // Control keys. 255 Operation.SET_MARK, /* Control-@ */ 256 Operation.BEGINNING_OF_LINE, /* Control-A */ 257 Operation.BACKWARD_CHAR, /* Control-B */ 258 Operation.INTERRUPT, /* Control-C */ 259 Operation.EXIT_OR_DELETE_CHAR, /* Control-D */ 260 Operation.END_OF_LINE, /* Control-E */ 261 Operation.FORWARD_CHAR, /* Control-F */ 262 Operation.ABORT, /* Control-G */ 263 Operation.BACKWARD_DELETE_CHAR, /* Control-H */ 264 Operation.COMPLETE, /* Control-I */ 265 Operation.ACCEPT_LINE, /* Control-J */ 266 Operation.KILL_LINE, /* Control-K */ 267 Operation.CLEAR_SCREEN, /* Control-L */ 268 Operation.ACCEPT_LINE, /* Control-M */ 269 Operation.NEXT_HISTORY, /* Control-N */ 270 null, /* Control-O */ 271 Operation.PREVIOUS_HISTORY, /* Control-P */ 272 Operation.QUOTED_INSERT, /* Control-Q */ 273 Operation.REVERSE_SEARCH_HISTORY, /* Control-R */ 274 Operation.FORWARD_SEARCH_HISTORY, /* Control-S */ 275 Operation.TRANSPOSE_CHARS, /* Control-T */ 276 Operation.UNIX_LINE_DISCARD, /* Control-U */ 277 Operation.QUOTED_INSERT, /* Control-V */ 278 Operation.UNIX_WORD_RUBOUT, /* Control-W */ 279 emacsCtrlX(), /* Control-X */ 280 Operation.YANK, /* Control-Y */ 281 null, /* Control-Z */ 282 emacsMeta(), /* Control-[ */ 283 null, /* Control-\ */ 284 Operation.CHARACTER_SEARCH, /* Control-] */ 285 null, /* Control-^ */ 286 Operation.UNDO, /* Control-_ */ 287 }; 288 System.arraycopy( ctrl, 0, map, 0, ctrl.length ); 289 for (int i = 32; i < 256; i++) { 290 map[i] = Operation.SELF_INSERT; 291 } 292 map[DELETE] = Operation.BACKWARD_DELETE_CHAR; 293 return new KeyMap(EMACS, map, false); 294 } 295 296 public static final char CTRL_D = (char) 4; 297 public static final char CTRL_G = (char) 7; 298 public static final char CTRL_H = (char) 8; 299 public static final char CTRL_I = (char) 9; 300 public static final char CTRL_J = (char) 10; 301 public static final char CTRL_M = (char) 13; 302 public static final char CTRL_R = (char) 18; 303 public static final char CTRL_S = (char) 19; 304 public static final char CTRL_U = (char) 21; 305 public static final char CTRL_X = (char) 24; 306 public static final char CTRL_Y = (char) 25; 307 public static final char ESCAPE = (char) 27; /* Ctrl-[ */ 308 public static final char CTRL_OB = (char) 27; /* Ctrl-[ */ 309 public static final char CTRL_CB = (char) 29; /* Ctrl-] */ 310 311 public static final int DELETE = (char) 127; 312 313 public static KeyMap emacsCtrlX() { 314 Object[] map = new Object[KEYMAP_LENGTH]; 315 map[CTRL_G] = Operation.ABORT; 316 map[CTRL_R] = Operation.RE_READ_INIT_FILE; 317 map[CTRL_U] = Operation.UNDO; 318 map[CTRL_X] = Operation.EXCHANGE_POINT_AND_MARK; 319 map['('] = Operation.START_KBD_MACRO; 320 map[')'] = Operation.END_KBD_MACRO; 321 for (int i = 'A'; i <= 'Z'; i++) { 322 map[i] = Operation.DO_LOWERCASE_VERSION; 323 } 324 map['e'] = Operation.CALL_LAST_KBD_MACRO; 325 map[DELETE] = Operation.KILL_LINE; 326 return new KeyMap(EMACS_CTLX, map, false); 327 } 328 329 public static KeyMap emacsMeta() { 330 Object[] map = new Object[KEYMAP_LENGTH]; 331 map[CTRL_G] = Operation.ABORT; 332 map[CTRL_H] = Operation.BACKWARD_KILL_WORD; 333 map[CTRL_I] = Operation.TAB_INSERT; 334 map[CTRL_J] = Operation.VI_EDITING_MODE; 335 map[CTRL_M] = Operation.VI_EDITING_MODE; 336 map[CTRL_R] = Operation.REVERT_LINE; 337 map[CTRL_Y] = Operation.YANK_NTH_ARG; 338 map[CTRL_OB] = Operation.COMPLETE; 339 map[CTRL_CB] = Operation.CHARACTER_SEARCH_BACKWARD; 340 map[' '] = Operation.SET_MARK; 341 map['#'] = Operation.INSERT_COMMENT; 342 map['&'] = Operation.TILDE_EXPAND; 343 map['*'] = Operation.INSERT_COMPLETIONS; 344 map['-'] = Operation.DIGIT_ARGUMENT; 345 map['.'] = Operation.YANK_LAST_ARG; 346 map['<'] = Operation.BEGINNING_OF_HISTORY; 347 map['='] = Operation.POSSIBLE_COMPLETIONS; 348 map['>'] = Operation.END_OF_HISTORY; 349 map['?'] = Operation.POSSIBLE_COMPLETIONS; 350 for (int i = 'A'; i <= 'Z'; i++) { 351 map[i] = Operation.DO_LOWERCASE_VERSION; 352 } 353 map['\\'] = Operation.DELETE_HORIZONTAL_SPACE; 354 map['_'] = Operation.YANK_LAST_ARG; 355 map['b'] = Operation.BACKWARD_WORD; 356 map['c'] = Operation.CAPITALIZE_WORD; 357 map['d'] = Operation.KILL_WORD; 358 map['f'] = Operation.FORWARD_WORD; 359 map['l'] = Operation.DOWNCASE_WORD; 360 map['p'] = Operation.NON_INCREMENTAL_REVERSE_SEARCH_HISTORY; 361 map['r'] = Operation.REVERT_LINE; 362 map['t'] = Operation.TRANSPOSE_WORDS; 363 map['u'] = Operation.UPCASE_WORD; 364 map['y'] = Operation.YANK_POP; 365 map['~'] = Operation.TILDE_EXPAND; 366 map[DELETE] = Operation.BACKWARD_KILL_WORD; 367 return new KeyMap(EMACS_META, map, false); 368 } 369 370 public static KeyMap viInsertion() { 371 Object[] map = new Object[KEYMAP_LENGTH]; 372 Object[] ctrl = new Object[] { 373 // Control keys. 374 null, /* Control-@ */ 375 Operation.SELF_INSERT, /* Control-A */ 376 Operation.SELF_INSERT, /* Control-B */ 377 Operation.SELF_INSERT, /* Control-C */ 378 Operation.VI_EOF_MAYBE, /* Control-D */ 379 Operation.SELF_INSERT, /* Control-E */ 380 Operation.SELF_INSERT, /* Control-F */ 381 Operation.SELF_INSERT, /* Control-G */ 382 Operation.BACKWARD_DELETE_CHAR, /* Control-H */ 383 Operation.COMPLETE, /* Control-I */ 384 Operation.ACCEPT_LINE, /* Control-J */ 385 Operation.SELF_INSERT, /* Control-K */ 386 Operation.SELF_INSERT, /* Control-L */ 387 Operation.ACCEPT_LINE, /* Control-M */ 388 Operation.MENU_COMPLETE, /* Control-N */ 389 Operation.SELF_INSERT, /* Control-O */ 390 Operation.MENU_COMPLETE_BACKWARD, /* Control-P */ 391 Operation.SELF_INSERT, /* Control-Q */ 392 Operation.REVERSE_SEARCH_HISTORY, /* Control-R */ 393 Operation.FORWARD_SEARCH_HISTORY, /* Control-S */ 394 Operation.TRANSPOSE_CHARS, /* Control-T */ 395 Operation.UNIX_LINE_DISCARD, /* Control-U */ 396 Operation.QUOTED_INSERT, /* Control-V */ 397 Operation.UNIX_WORD_RUBOUT, /* Control-W */ 398 Operation.SELF_INSERT, /* Control-X */ 399 Operation.YANK, /* Control-Y */ 400 Operation.SELF_INSERT, /* Control-Z */ 401 Operation.VI_MOVEMENT_MODE, /* Control-[ */ 402 Operation.SELF_INSERT, /* Control-\ */ 403 Operation.SELF_INSERT, /* Control-] */ 404 Operation.SELF_INSERT, /* Control-^ */ 405 Operation.UNDO, /* Control-_ */ 406 }; 407 System.arraycopy( ctrl, 0, map, 0, ctrl.length ); 408 for (int i = 32; i < 256; i++) { 409 map[i] = Operation.SELF_INSERT; 410 } 411 map[DELETE] = Operation.BACKWARD_DELETE_CHAR; 412 return new KeyMap(VI_INSERT, map, false); 413 } 414 415 public static KeyMap viMovement() { 416 Object[] map = new Object[KEYMAP_LENGTH]; 417 Object[] low = new Object[] { 418 // Control keys. 419 null, /* Control-@ */ 420 null, /* Control-A */ 421 null, /* Control-B */ 422 Operation.INTERRUPT, /* Control-C */ 423 /* 424 * ^D is supposed to move down half a screen. In bash 425 * appears to be ignored. 426 */ 427 Operation.VI_EOF_MAYBE, /* Control-D */ 428 Operation.EMACS_EDITING_MODE, /* Control-E */ 429 null, /* Control-F */ 430 Operation.ABORT, /* Control-G */ 431 Operation.BACKWARD_CHAR, /* Control-H */ 432 null, /* Control-I */ 433 Operation.VI_MOVE_ACCEPT_LINE, /* Control-J */ 434 Operation.KILL_LINE, /* Control-K */ 435 Operation.CLEAR_SCREEN, /* Control-L */ 436 Operation.VI_MOVE_ACCEPT_LINE, /* Control-M */ 437 Operation.VI_NEXT_HISTORY, /* Control-N */ 438 null, /* Control-O */ 439 Operation.VI_PREVIOUS_HISTORY, /* Control-P */ 440 /* 441 * My testing with readline is the ^Q is ignored. 442 * Maybe this should be null? 443 */ 444 Operation.QUOTED_INSERT, /* Control-Q */ 445 446 /* 447 * TODO - Very broken. While in forward/reverse 448 * history search the VI keyset should go out the 449 * window and we need to enter a very simple keymap. 450 */ 451 Operation.REVERSE_SEARCH_HISTORY, /* Control-R */ 452 /* TODO */ 453 Operation.FORWARD_SEARCH_HISTORY, /* Control-S */ 454 Operation.TRANSPOSE_CHARS, /* Control-T */ 455 Operation.UNIX_LINE_DISCARD, /* Control-U */ 456 /* TODO */ 457 Operation.QUOTED_INSERT, /* Control-V */ 458 Operation.UNIX_WORD_RUBOUT, /* Control-W */ 459 null, /* Control-X */ 460 /* TODO */ 461 Operation.YANK, /* Control-Y */ 462 null, /* Control-Z */ 463 emacsMeta(), /* Control-[ */ 464 null, /* Control-\ */ 465 /* TODO */ 466 Operation.CHARACTER_SEARCH, /* Control-] */ 467 null, /* Control-^ */ 468 /* TODO */ 469 Operation.UNDO, /* Control-_ */ 470 Operation.FORWARD_CHAR, /* SPACE */ 471 null, /* ! */ 472 null, /* " */ 473 Operation.VI_INSERT_COMMENT, /* # */ 474 Operation.END_OF_LINE, /* $ */ 475 Operation.VI_MATCH, /* % */ 476 Operation.VI_TILDE_EXPAND, /* & */ 477 null, /* ' */ 478 null, /* ( */ 479 null, /* ) */ 480 /* TODO */ 481 Operation.VI_COMPLETE, /* * */ 482 Operation.VI_NEXT_HISTORY, /* + */ 483 Operation.VI_CHAR_SEARCH, /* , */ 484 Operation.VI_PREVIOUS_HISTORY, /* - */ 485 /* TODO */ 486 Operation.VI_REDO, /* . */ 487 Operation.VI_SEARCH, /* / */ 488 Operation.VI_BEGNNING_OF_LINE_OR_ARG_DIGIT, /* 0 */ 489 Operation.VI_ARG_DIGIT, /* 1 */ 490 Operation.VI_ARG_DIGIT, /* 2 */ 491 Operation.VI_ARG_DIGIT, /* 3 */ 492 Operation.VI_ARG_DIGIT, /* 4 */ 493 Operation.VI_ARG_DIGIT, /* 5 */ 494 Operation.VI_ARG_DIGIT, /* 6 */ 495 Operation.VI_ARG_DIGIT, /* 7 */ 496 Operation.VI_ARG_DIGIT, /* 8 */ 497 Operation.VI_ARG_DIGIT, /* 9 */ 498 null, /* : */ 499 Operation.VI_CHAR_SEARCH, /* ; */ 500 null, /* < */ 501 Operation.VI_COMPLETE, /* = */ 502 null, /* > */ 503 Operation.VI_SEARCH, /* ? */ 504 null, /* @ */ 505 Operation.VI_APPEND_EOL, /* A */ 506 Operation.VI_PREV_WORD, /* B */ 507 Operation.VI_CHANGE_TO_EOL, /* C */ 508 Operation.VI_DELETE_TO_EOL, /* D */ 509 Operation.VI_END_WORD, /* E */ 510 Operation.VI_CHAR_SEARCH, /* F */ 511 /* I need to read up on what this does */ 512 Operation.VI_FETCH_HISTORY, /* G */ 513 null, /* H */ 514 Operation.VI_INSERT_BEG, /* I */ 515 null, /* J */ 516 null, /* K */ 517 null, /* L */ 518 null, /* M */ 519 Operation.VI_SEARCH_AGAIN, /* N */ 520 null, /* O */ 521 Operation.VI_PUT, /* P */ 522 null, /* Q */ 523 /* TODO */ 524 Operation.VI_REPLACE, /* R */ 525 Operation.VI_KILL_WHOLE_LINE, /* S */ 526 Operation.VI_CHAR_SEARCH, /* T */ 527 /* TODO */ 528 Operation.REVERT_LINE, /* U */ 529 null, /* V */ 530 Operation.VI_NEXT_WORD, /* W */ 531 Operation.VI_RUBOUT, /* X */ 532 Operation.VI_YANK_TO, /* Y */ 533 null, /* Z */ 534 null, /* [ */ 535 Operation.VI_COMPLETE, /* \ */ 536 null, /* ] */ 537 Operation.VI_FIRST_PRINT, /* ^ */ 538 Operation.VI_YANK_ARG, /* _ */ 539 Operation.VI_GOTO_MARK, /* ` */ 540 Operation.VI_APPEND_MODE, /* a */ 541 Operation.VI_PREV_WORD, /* b */ 542 Operation.VI_CHANGE_TO, /* c */ 543 Operation.VI_DELETE_TO, /* d */ 544 Operation.VI_END_WORD, /* e */ 545 Operation.VI_CHAR_SEARCH, /* f */ 546 null, /* g */ 547 Operation.BACKWARD_CHAR, /* h */ 548 Operation.VI_INSERTION_MODE, /* i */ 549 Operation.NEXT_HISTORY, /* j */ 550 Operation.PREVIOUS_HISTORY, /* k */ 551 Operation.FORWARD_CHAR, /* l */ 552 Operation.VI_SET_MARK, /* m */ 553 Operation.VI_SEARCH_AGAIN, /* n */ 554 null, /* o */ 555 Operation.VI_PUT, /* p */ 556 null, /* q */ 557 Operation.VI_CHANGE_CHAR, /* r */ 558 Operation.VI_SUBST, /* s */ 559 Operation.VI_CHAR_SEARCH, /* t */ 560 Operation.UNDO, /* u */ 561 null, /* v */ 562 Operation.VI_NEXT_WORD, /* w */ 563 Operation.VI_DELETE, /* x */ 564 Operation.VI_YANK_TO, /* y */ 565 null, /* z */ 566 null, /* { */ 567 Operation.VI_COLUMN, /* | */ 568 null, /* } */ 569 Operation.VI_CHANGE_CASE, /* ~ */ 570 Operation.VI_DELETE /* DEL */ 571 }; 572 System.arraycopy( low, 0, map, 0, low.length ); 573 for (int i = 128; i < 256; i++) { 574 map[i] = null; 575 } 576 return new KeyMap(VI_MOVE, map, false); 577 } 578 }