1 19 package jline; 20 21 import java.io.*; 22 import java.text.*; 23 import java.util.*; 24 25 45 public class ConsoleReader 46 { 47 String prompt; 48 49 public static final String CR = System.getProperty ("line.separator"); 50 51 public static final char BACKSPACE = '\b'; 52 public static final char RESET_LINE = '\r'; 53 public static final char KEYBOARD_BELL = '\07'; 54 55 56 public static final short ARROW_START = 27; 57 public static final short ARROW_PREFIX = 91; 58 public static final short ARROW_LEFT = 68; 59 public static final short ARROW_RIGHT = 67; 60 public static final short ARROW_UP = 65; 61 public static final short ARROW_DOWN = 66; 62 63 64 67 68 71 public static final short UNKNOWN = -99; 72 73 76 public static final short MOVE_TO_BEG = -1; 77 78 81 public static final short MOVE_TO_END = -3; 82 83 86 public static final short PREV_CHAR = -4; 87 88 91 public static final short NEWLINE = -6; 92 93 96 public static final short KILL_LINE = -7; 97 98 101 public static final short CLEAR_SCREEN = -8; 102 103 106 public static final short NEXT_HISTORY = -9; 107 108 111 public static final short PREV_HISTORY = -11; 112 113 116 public static final short REDISPLAY = -13; 117 118 121 public static final short KILL_LINE_PREV = -15; 122 123 126 public static final short DELETE_PREV_WORD = -16; 127 128 131 public static final short NEXT_CHAR = -19; 132 133 136 public static final short REPEAT_PREV_CHAR = -20; 137 138 141 public static final short SEARCH_PREV = -21; 142 143 146 public static final short REPEAT_NEXT_CHAR = -24; 147 148 151 public static final short SEARCH_NEXT = -25; 152 153 156 public static final short PREV_SPACE_WORD = -27; 157 158 161 public static final short TO_END_WORD = -29; 162 163 166 public static final short REPEAT_SEARCH_PREV = -34; 167 168 171 public static final short PASTE_PREV = -36; 172 173 176 public static final short REPLACE_MODE = -37; 177 178 181 public static final short SUBSTITUTE_LINE = -38; 182 183 186 public static final short TO_PREV_CHAR = -39; 187 188 191 public static final short NEXT_SPACE_WORD = -40; 192 193 196 public static final short DELETE_PREV_CHAR = -41; 197 198 201 public static final short ADD = -42; 202 203 206 public static final short PREV_WORD = -43; 207 208 211 public static final short CHANGE_META = -44; 212 213 216 public static final short DELETE_META = -45; 217 218 221 public static final short END_WORD = -46; 222 223 226 public static final short INSERT = -48; 227 228 231 public static final short REPEAT_SEARCH_NEXT = -49; 232 233 236 public static final short PASTE_NEXT = -50; 237 238 241 public static final short REPLACE_CHAR = -51; 242 243 246 public static final short SUBSTITUTE_CHAR = -52; 247 248 251 public static final short TO_NEXT_CHAR = -53; 252 253 256 public static final short UNDO = -54; 257 258 261 public static final short NEXT_WORD = -55; 262 263 266 public static final short DELETE_NEXT_CHAR = -56; 267 268 271 public static final short CHANGE_CASE = -57; 272 273 276 public static final short COMPLETE = -58; 277 278 281 public static final short EXIT = -59; 282 283 284 287 public static SortedMap KEYMAP_NAMES; 288 289 static 290 { 291 Map names = new TreeMap (); 292 293 names.put ("MOVE_TO_BEG", new Short (MOVE_TO_BEG)); 294 names.put ("MOVE_TO_END", new Short (MOVE_TO_END)); 295 names.put ("PREV_CHAR", new Short (PREV_CHAR)); 296 names.put ("NEWLINE", new Short (NEWLINE)); 297 names.put ("KILL_LINE", new Short (KILL_LINE)); 298 names.put ("CLEAR_SCREEN", new Short (CLEAR_SCREEN)); 299 names.put ("NEXT_HISTORY", new Short (NEXT_HISTORY)); 300 names.put ("PREV_HISTORY", new Short (PREV_HISTORY)); 301 names.put ("REDISPLAY", new Short (REDISPLAY)); 302 names.put ("KILL_LINE_PREV", new Short (KILL_LINE_PREV)); 303 names.put ("DELETE_PREV_WORD", new Short (DELETE_PREV_WORD)); 304 names.put ("NEXT_CHAR", new Short (NEXT_CHAR)); 305 names.put ("REPEAT_PREV_CHAR", new Short (REPEAT_PREV_CHAR)); 306 names.put ("SEARCH_PREV", new Short (SEARCH_PREV)); 307 names.put ("REPEAT_NEXT_CHAR", new Short (REPEAT_NEXT_CHAR)); 308 names.put ("SEARCH_NEXT", new Short (SEARCH_NEXT)); 309 names.put ("PREV_SPACE_WORD", new Short (PREV_SPACE_WORD)); 310 names.put ("TO_END_WORD", new Short (TO_END_WORD)); 311 names.put ("REPEAT_SEARCH_PREV", new Short (REPEAT_SEARCH_PREV)); 312 names.put ("PASTE_PREV", new Short (PASTE_PREV)); 313 names.put ("REPLACE_MODE", new Short (REPLACE_MODE)); 314 names.put ("SUBSTITUTE_LINE", new Short (SUBSTITUTE_LINE)); 315 names.put ("TO_PREV_CHAR", new Short (TO_PREV_CHAR)); 316 names.put ("NEXT_SPACE_WORD", new Short (NEXT_SPACE_WORD)); 317 names.put ("DELETE_PREV_CHAR", new Short (DELETE_PREV_CHAR)); 318 names.put ("ADD", new Short (ADD)); 319 names.put ("PREV_WORD", new Short (PREV_WORD)); 320 names.put ("CHANGE_META", new Short (CHANGE_META)); 321 names.put ("DELETE_META", new Short (DELETE_META)); 322 names.put ("END_WORD", new Short (END_WORD)); 323 names.put ("NEXT_CHAR", new Short (NEXT_CHAR)); 324 names.put ("INSERT", new Short (INSERT)); 325 names.put ("REPEAT_SEARCH_NEXT", new Short (REPEAT_SEARCH_NEXT)); 326 names.put ("PASTE_NEXT", new Short (PASTE_NEXT)); 327 names.put ("REPLACE_CHAR", new Short (REPLACE_CHAR)); 328 names.put ("SUBSTITUTE_CHAR", new Short (SUBSTITUTE_CHAR)); 329 names.put ("TO_NEXT_CHAR", new Short (TO_NEXT_CHAR)); 330 names.put ("UNDO", new Short (UNDO)); 331 names.put ("NEXT_WORD", new Short (NEXT_WORD)); 332 names.put ("DELETE_NEXT_CHAR", new Short (DELETE_NEXT_CHAR)); 333 names.put ("CHANGE_CASE", new Short (CHANGE_CASE)); 334 names.put ("COMPLETE", new Short (COMPLETE)); 335 names.put ("EXIT", new Short (EXIT)); 336 337 KEYMAP_NAMES = new TreeMap (Collections.unmodifiableMap (names)); 338 } 339 340 341 344 private final short [] keybindings; 345 346 347 350 private boolean bellEnabled = true; 351 352 353 356 private Character mask = null; 357 358 359 362 private static final Character NULL_MASK = new Character ((char)0); 363 364 365 369 private int autoprintThreshhold = Integer.getInteger ( 370 "jline.completion.threshold", 100).intValue (); 372 373 376 private final Terminal terminal; 377 378 379 private CompletionHandler completionHandler 380 = new CandidateListCompletionHandler (); 381 382 383 InputStream in; 384 final Writer out; 385 final CursorBuffer buf = new CursorBuffer (); 386 static PrintWriter debugger; 387 History history = new History (); 388 final List completors = new LinkedList (); 389 390 private Character echoCharacter = null; 391 392 393 398 public ConsoleReader () 399 throws IOException 400 { 401 this (new FileInputStream (FileDescriptor.in), 402 new PrintWriter (System.out)); 403 } 404 405 406 411 public ConsoleReader (InputStream in, Writer out) 412 throws IOException 413 { 414 this (in, out, null); 415 } 416 417 418 public ConsoleReader (InputStream in, Writer out, InputStream bindings) 419 throws IOException 420 { 421 this (in, out, bindings, Terminal.getTerminal ()); 422 } 423 424 425 433 public ConsoleReader (InputStream in, Writer out, InputStream bindings, 434 Terminal term) 435 throws IOException 436 { 437 this.terminal = term; 438 setInput (in); 439 this.out = out; 440 if (bindings == null) 441 { 442 String bindingFile = System.getProperty ("jline.keybindings", 443 new File (System.getProperty ("user.home", 444 ".jlinebindings.properties")).getAbsolutePath ()); 445 446 if (!(new File (bindingFile).isFile ())) 447 bindings = ConsoleReader.class.getResourceAsStream ( 448 "keybindings.properties"); 449 else 450 bindings = new FileInputStream (new File (bindingFile)); 451 } 452 453 this.keybindings = new short [Byte.MAX_VALUE * 2]; 454 455 Arrays.fill (this.keybindings, UNKNOWN); 456 457 462 if (bindings != null) 463 { 464 Properties p = new Properties (); 465 p.load (bindings); 466 bindings.close (); 467 468 for (Iterator i = p.keySet ().iterator (); i.hasNext (); ) 469 { 470 String val = (String )i.next (); 471 try 472 { 473 Short code = new Short (val); 474 String op = (String )p.getProperty (val); 475 476 Short opval = (Short )KEYMAP_NAMES.get (op); 477 478 if (opval != null) 479 keybindings [code.shortValue ()] = opval.shortValue (); 480 } 481 catch (NumberFormatException nfe) 482 { 483 } 484 } 485 } 486 487 488 491 keybindings [ARROW_START] = ARROW_START; 492 } 493 494 495 public Terminal getTerminal () 496 { 497 return this.terminal; 498 } 499 500 501 502 505 public void setDebug (PrintWriter debugger) 506 { 507 this.debugger = debugger; 508 } 509 510 511 514 public void setInput (InputStream in) 515 { 516 this.in = in; 517 } 518 519 520 523 public InputStream getInput () 524 { 525 return this.in; 526 } 527 528 529 532 public String readLine () 533 throws IOException 534 { 535 return readLine ((String )null); 536 } 537 538 539 543 public String readLine (Character mask) 544 throws IOException 545 { 546 return readLine (null, mask); 547 } 548 549 550 554 public void setBellEnabled (boolean bellEnabled) 555 { 556 this.bellEnabled = bellEnabled; 557 } 558 559 560 563 public boolean getBellEnabled () 564 { 565 return this.bellEnabled; 566 } 567 568 569 575 public int getTermwidth () 576 { 577 return Terminal.setupTerminal ().getTerminalWidth (); 578 } 579 580 581 588 public int getTermheight () 589 { 590 return Terminal.setupTerminal ().getTerminalHeight (); 591 } 592 593 594 598 public void setAutoprintThreshhold (int autoprintThreshhold) 599 { 600 this.autoprintThreshhold = autoprintThreshhold; 601 } 602 603 604 607 public int getAutoprintThreshhold () 608 { 609 return this.autoprintThreshhold; 610 } 611 612 613 int getKeyForAction (short logicalAction) 614 { 615 for (int i = 0; i < keybindings.length; i++) 616 { 617 if (keybindings [i] == logicalAction) 618 { 619 return i; 620 } 621 } 622 623 return -1; 624 } 625 626 627 630 int clearEcho (int c) 631 throws IOException 632 { 633 if (!terminal.getEcho ()) 635 return 0; 636 637 int num = countEchoCharacters ((char)c); 639 back (num); 640 drawBuffer (num); 641 642 return num; 643 } 644 645 646 int countEchoCharacters (char c) 647 { 648 if (c == 9) 651 { 652 int tabstop = 8; int position = getCursorPosition (); 654 return tabstop - (position % tabstop); 655 } 656 657 return getPrintableCharacters (c).length (); 658 } 659 660 661 667 StringBuffer getPrintableCharacters (char ch) 668 { 669 StringBuffer sbuff = new StringBuffer (); 670 if (ch >= 32) 671 { 672 if (ch < 127) 673 { 674 sbuff.append (ch); 675 } 676 else if (ch == 127) 677 { 678 sbuff.append ('^'); 679 sbuff.append ('?'); 680 } 681 else 682 { 683 sbuff.append ('M'); 684 sbuff.append ('-'); 685 if (ch >= 128 + 32) 686 { 687 if (ch < 128 + 127) 688 { 689 sbuff.append ((char)(ch - 128)); 690 } 691 else 692 { 693 sbuff.append ('^'); 694 sbuff.append ('?'); 695 } 696 } 697 else 698 { 699 sbuff.append ('^'); 700 sbuff.append ((char)(ch - 128 + 64)); 701 } 702 } 703 } 704 else 705 { 706 sbuff.append ('^'); 707 sbuff.append ((char)(ch + 64)); 708 } 709 710 return sbuff; 711 } 712 713 714 int getCursorPosition () 715 { 716 return (prompt == null ? 0 : prompt.length ()) 718 + buf.cursor; } 720 721 722 public String readLine (String prompt) 723 throws IOException 724 { 725 return readLine (prompt, null); 726 } 727 728 729 737 public String readLine (String prompt, Character mask) 738 throws IOException 739 { 740 this.mask = mask; 741 this.prompt = prompt; 742 743 if (prompt != null && prompt.length () > 0) 744 { 745 out.write (prompt); 746 out.flush (); 747 } 748 749 if (!terminal.isSupported ()) 751 return new BufferedReader (new InputStreamReader (in)).readLine (); 752 753 int c; 754 755 while (true) 756 { 757 if ((c = readCharacter ()) == -1) 758 return null; 759 760 boolean success = true; 761 762 short code = keybindings [c]; 764 765 if (debugger != null) 766 debug (" translated: " + (int)c + ": " + code); 767 768 switch (code) 769 { 770 case EXIT: if (buf.buffer.length () == 0) 772 return null; 773 case COMPLETE: success = complete (); 775 break; 776 case MOVE_TO_BEG: 777 success = setCursorPosition (0); 778 break; 779 case KILL_LINE: success = killLine (); 781 break; 782 case KILL_LINE_PREV: success = resetLine (); 784 break; 785 case ARROW_START: 786 788 switch (c = readCharacter ()) 789 { 790 case ARROW_PREFIX: 791 793 switch (c = readCharacter ()) 794 { 795 case ARROW_LEFT: success = moveCursor (-1) != 0; 798 break; 799 case ARROW_RIGHT: success = moveCursor (1) != 0; 802 break; 803 case ARROW_UP: success = moveHistory (false); 806 break; 807 case ARROW_DOWN: success = moveHistory (true); 810 break; 811 default: 812 break; 813 814 } 815 break; 816 default: 817 break; 818 } 819 break; 820 case NEWLINE: printNewline (); return finishBuffer (); 823 case DELETE_PREV_CHAR: success = backspace (); 825 break; 826 case MOVE_TO_END: 827 success = moveToEnd (); 828 break; 829 case PREV_CHAR: 830 success = moveCursor (-1) != 0; 831 break; 832 case NEXT_CHAR: 833 success = moveCursor (1) != 0; 834 break; 835 case NEXT_HISTORY: 836 success = moveHistory (true); 837 break; 838 case PREV_HISTORY: 839 success = moveHistory (false); 840 break; 841 case REDISPLAY: 842 break; 843 case DELETE_PREV_WORD: 844 success = deletePreviousWord (); 845 break; 846 case PREV_WORD: 847 success = previousWord (); 848 break; 849 850 case UNKNOWN: 851 default: 852 putChar (c, true); 853 } 854 855 if (!(success)) 856 beep (); 857 858 flushConsole (); 859 } 860 } 861 862 863 868 private final boolean moveHistory (boolean next) 869 throws IOException 870 { 871 if (next && !history.next ()) 872 return false; 873 else if (!next && !history.previous ()) 874 return false; 875 876 setBuffer (history.current ()); 877 return true; 878 } 879 880 881 886 public boolean killLine () 887 throws IOException 888 { 889 int cp = buf.cursor; 890 int len = buf.buffer.length (); 891 if (cp >= len) 892 return false; 893 894 int num = buf.buffer.length () - cp; 895 clearAhead (num); 896 for (int i = 0; i < num; i++) 897 buf.buffer.deleteCharAt (len - i - 1); 898 return true; 899 } 900 901 902 908 private final boolean complete () 909 throws IOException 910 { 911 913 if (completors.size () == 0) 914 return false; 915 916 List candidates = new LinkedList (); 917 String bufstr = buf.buffer.toString (); 918 int cursor = buf.cursor; 919 920 int position = -1; 921 922 for (Iterator i = completors.iterator (); i.hasNext (); ) 923 { 924 Completor comp = (Completor)i.next (); 925 if ((position = comp.complete (bufstr, cursor, candidates)) != -1) 926 break; 927 } 928 929 if (candidates.size () == 0) 931 return false; 932 933 return completionHandler.complete (this, candidates, position); 934 } 935 936 937 public CursorBuffer getCursorBuffer () 938 { 939 return buf; 940 } 941 942 943 948 public void printColumns (Collection stuff) 949 throws IOException 950 { 951 if (stuff == null || stuff.size () == 0) 952 return; 953 954 int width = getTermwidth (); 955 int maxwidth = 0; 956 for (Iterator i = stuff.iterator (); i.hasNext (); 957 maxwidth = Math.max (maxwidth, i.next ().toString ().length ())); 958 959 StringBuffer line = new StringBuffer (); 960 961 for (Iterator i = stuff.iterator (); i.hasNext (); ) 962 { 963 String cur = (String )i.next (); 964 965 if (line.length () + maxwidth > width) 966 { 967 printString (line.toString ().trim ()); 968 printNewline (); 969 line.setLength (0); 970 } 971 972 pad (cur, maxwidth + 3, line); 973 } 974 975 if (line.length () > 0) 976 { 977 printString (line.toString ().trim ()); 978 printNewline (); 979 line.setLength (0); 980 } 981 } 982 983 984 993 private final void pad (String toPad, int len, StringBuffer appendTo) 994 { 995 appendTo.append (toPad); 996 for (int i = 0; i < (len - toPad.length ()); 997 i++, appendTo.append (' ')); 998 } 999 1000 1001 1008 public boolean addCompletor (Completor completor) 1009 { 1010 return completors.add (completor); 1011 } 1012 1013 1014 1021 public boolean removeCompletor (Completor completor) 1022 { 1023 return completors.remove (completor); 1024 } 1025 1026 1027 1030 public Collection getCompletors () 1031 { 1032 return Collections.unmodifiableList (completors); 1033 } 1034 1035 1036 1041 final boolean resetLine () 1042 throws IOException 1043 { 1044 if (buf.cursor == 0) 1045 return false; 1046 1047 backspaceAll (); 1048 1049 return true; 1050 } 1051 1052 1053 1056 public final boolean setCursorPosition (int position) 1057 throws IOException 1058 { 1059 return moveCursor (position - buf.cursor) != 0; 1060 } 1061 1062 1063 1070 private final void setBuffer (String buffer) 1071 throws IOException 1072 { 1073 if (buffer.equals (buf.buffer.toString ())) 1075 return; 1076 1077 int sameIndex = 0; 1079 for (int i = 0, l1 = buffer.length (), l2 = buf.buffer.length (); 1080 i < l1 && i < l2; i++) 1081 { 1082 if (buffer.charAt (i) == buf.buffer.charAt (i)) 1083 sameIndex++; 1084 else 1085 break; 1086 } 1087 1088 int diff = buf.buffer.length () - sameIndex; 1089 1090 backspace (diff); killLine (); buf.buffer.setLength (sameIndex); putString (buffer.substring (sameIndex)); } 1095 1096 1097 1100 public final void redrawLine () 1101 throws IOException 1102 { 1103 printCharacter (RESET_LINE); 1104 flushConsole (); 1105 drawLine (); 1106 } 1107 1108 1109 1112 public final void drawLine () 1113 throws IOException 1114 { 1115 if (prompt != null) 1116 printString (prompt); 1117 printString (buf.buffer.toString ()); 1118 } 1119 1120 1121 1124 public final void printNewline () 1125 throws IOException 1126 { 1127 printString (CR); 1128 flushConsole (); 1129 } 1130 1131 1132 1137 final String finishBuffer () 1138 { 1139 String str = buf.buffer.toString (); 1140 1141 if (str.length () > 0) 1143 history.addToHistory (str); 1144 1145 history.moveToEnd (); 1146 1147 buf.buffer.setLength (0); 1148 buf.cursor = 0; 1149 return str; 1150 } 1151 1152 1153 1157 public final void putString (String str) 1158 throws IOException 1159 { 1160 buf.insert (str); 1161 printString (str); 1162 drawBuffer (); 1163 } 1164 1165 1166 1170 public final void printString (String str) 1171 throws IOException 1172 { 1173 printCharacters (str.toCharArray ()); 1174 } 1175 1176 1177 1181 private final void putChar (int c, boolean print) 1182 throws IOException 1183 { 1184 buf.insert ((char)c); 1185 1186 if (print) 1187 { 1188 if (mask == null) 1190 { 1191 printCharacter (c); 1192 } 1193 else if (mask.charValue () == 0) 1195 { 1196 } 1197 else 1199 { 1200 printCharacter (mask.charValue ()); 1201 } 1202 drawBuffer (); 1203 } 1204 } 1205 1206 1207 1214 private final void drawBuffer (int clear) 1215 throws IOException 1216 { 1217 1219 char [] chars = buf.buffer.substring (buf.cursor).toCharArray (); 1220 printCharacters (chars); 1221 1222 clearAhead (clear); 1223 back (chars.length); 1224 flushConsole (); 1225 } 1226 1227 1228 1232 private final void drawBuffer () 1233 throws IOException 1234 { 1235 drawBuffer (0); 1236 } 1237 1238 1239 1243 private final void clearAhead (int num) 1244 throws IOException 1245 { 1246 if (num == 0) 1247 return; 1248 1249 1251 printCharacters (' ', num); 1253 1254 flushConsole (); 1258 1259 back (num); 1261 1262 flushConsole (); 1263 } 1264 1265 1266 1270 private final void back (int num) 1271 throws IOException 1272 { 1273 printCharacters (BACKSPACE, num); 1274 flushConsole (); 1275 } 1276 1277 1278 1282 public final void beep () 1283 throws IOException 1284 { 1285 if (!(getBellEnabled ())) 1286 return; 1287 1288 printCharacter (KEYBOARD_BELL); 1289 flushConsole (); 1291 } 1292 1293 1294 1298 private final void printCharacter (int c) 1299 throws IOException 1300 { 1301 out.write (c); 1302 } 1303 1304 1305 1309 private final void printCharacters (char [] c) 1310 throws IOException 1311 { 1312 out.write (c); 1313 } 1314 1315 1316 private final void printCharacters (char c, int num) 1317 throws IOException 1318 { 1319 if (num == 1) 1320 { 1321 printCharacter (c); 1322 } 1323 else 1324 { 1325 char [] chars = new char [num]; 1326 Arrays.fill (chars, c); 1327 printCharacters (chars); 1328 } 1329 } 1330 1331 1332 1337 public final void flushConsole () 1338 throws IOException 1339 { 1340 out.flush (); 1341 } 1342 1343 1344 private final int backspaceAll () 1345 throws IOException 1346 { 1347 return backspace (Integer.MAX_VALUE); 1348 } 1349 1350 1351 1356 private final int backspace (int num) 1357 throws IOException 1358 { 1359 if (buf.cursor == 0) 1360 return 0; 1361 1362 int count = 0; 1363 1364 count = moveCursor (-1 * num) * -1; 1365 1367 buf.buffer.delete (buf.cursor, buf.cursor + count); 1368 drawBuffer (count); 1369 1370 return count; 1371 } 1372 1373 1374 1379 public final boolean backspace () 1380 throws IOException 1381 { 1382 return backspace (1) == 1; 1383 } 1384 1385 1386 private final boolean moveToEnd () 1387 throws IOException 1388 { 1389 if (moveCursor (1) == 0) 1390 return false; 1391 1392 while (moveCursor (1) != 0); 1393 1394 return true; 1395 } 1396 1397 1398 1402 private final boolean deleteCurrentCharacter () 1403 throws IOException 1404 { 1405 buf.buffer.deleteCharAt (buf.cursor); 1406 drawBuffer (1); 1407 return true; 1408 } 1409 1410 1411 private final boolean previousWord () 1412 throws IOException 1413 { 1414 while (Character.isWhitespace (buf.current ()) && moveCursor (-1)!= 0); 1415 while (!Character.isWhitespace (buf.current ()) && moveCursor (-1)!= 0); 1416 1417 return true; 1418 } 1419 1420 1421 private final boolean deletePreviousWord () 1422 throws IOException 1423 { 1424 while (Character.isWhitespace (buf.current ()) && backspace ()); 1425 while (!Character.isWhitespace (buf.current ()) && backspace ()); 1426 1427 return true; 1428 } 1429 1430 1431 1439 private final int moveCursor (int where) 1440 throws IOException 1441 { 1442 if (buf.cursor == 0 && where < 0) 1443 return 0; 1444 1445 if (buf.cursor == buf.buffer.length () && where > 0) 1446 return 0; 1447 1448 if (buf.cursor + where < 0) 1449 where = -buf.cursor; 1450 else if (buf.cursor + where > buf.buffer.length ()) 1451 where = buf.buffer.length () - buf.cursor; 1452 1453 moveInternal (where); 1454 return where; 1455 } 1456 1457 1458 1463 public static void debug (String str) 1464 { 1465 if (debugger != null) 1466 { 1467 debugger.println (str); 1468 debugger.flush (); 1469 } 1470 } 1471 1472 1473 1481 private final void moveInternal (int where) 1482 throws IOException 1483 { 1484 1487 buf.cursor += where; 1488 1489 char c; 1490 1491 if (where < 0) 1492 { 1493 c = BACKSPACE; 1494 } 1495 else if (buf.cursor == 0) 1496 { 1497 return; 1498 } 1499 else 1500 { 1501 c = buf.buffer.charAt (buf.cursor - 1); } 1503 1504 if (NULL_MASK.equals (mask)) 1506 return; 1507 1508 printCharacters (c, Math.abs (where)); 1509 } 1510 1511 1512 1517 public final int readCharacter () 1518 throws IOException 1519 { 1520 int c = in.read (); 1521 1522 if (debugger != null) 1523 debug ("keystroke: " + c + ""); 1524 1525 clearEcho (c); 1527 1528 return c; 1529 } 1530 1531 1532 public final int readCharacter (char[] allowed) 1533 throws IOException 1534 { 1535 1536 char c; 1539 1540 Arrays.sort (allowed); while (Arrays.binarySearch (allowed, c = (char)readCharacter ()) == -1); 1542 1543 return c; 1544 } 1545 1546 1547 public void setHistory (History history) 1548 { 1549 this.history = history; 1550 } 1551 1552 1553 public History getHistory () 1554 { 1555 return this.history; 1556 } 1557 1558 1559 public void setCompletionHandler (CompletionHandler completionHandler) 1560 { 1561 this.completionHandler = completionHandler; 1562 } 1563 1564 1565 public CompletionHandler getCompletionHandler () 1566 { 1567 return this.completionHandler; 1568 } 1569 1570 1571 1572 1591 public void setEchoCharacter (Character echoCharacter) 1592 { 1593 this.echoCharacter = echoCharacter; 1594 } 1595 1596 1597 1600 public Character getEchoCharacter () 1601 { 1602 return this.echoCharacter; 1603 } 1604} 1605 1606 | Popular Tags |