|
Terminal |
|
1 // joi/8/terminal/Terminal.java 2 // (and terminal/Terminal.java) 3 // 4 // Copyright 2003 Bill Campbell and Ethan Bolker 5 6 import java.io.*; 7 8 /** 9 * Terminal provides a user-friendly interface to the standard System 10 * input and output streams (in, out, and err). 11 * <p> 12 * A Terminal is an object. In general, one is expected to instantiate 13 * just one Terminal. Although one might instantiate several, all will 14 * share the same System streams. 15 * <p> 16 * A Terminal may either explicitly echo input, or not. Echoing input 17 * is useful, for example, when testing with I/O redirection. 18 * <p> 19 * Inspired by Cay Horstmann's Console Class. 20 */ 21 22 public class Terminal 23 { 24 private boolean echo = false; 25 private static BufferedReader in = 26 new BufferedReader(new FileReader(FileDescriptor.in)); 27 28 29 // Print a prompt to the console without a newline. 30 31 private void printPrompt( String prompt ) 32 { 33 print( prompt ); 34 System.out.flush(); 35 } 36 37 /** 38 * Construct a Terminal that doesn't echo input. 39 */ 40 41 public Terminal() 42 { 43 this( false ); 44 } 45 46 /** 47 * Construct a Terminal. 48 * 49 * @param echo whether or not input should be echoed. 50 */ 51 52 public Terminal( boolean echo ) 53 { 54 this.echo = echo; 55 } 56 57 /** 58 * Read a line (terminated by a newline) from the Terminal. 59 * @param prompt output string to prompt for input. 60 * 61 * @return the string (without the newline character), 62 * null if eof. 63 */ 64 65 public String readLine( String prompt ) 66 { 67 printPrompt(prompt); 68 try { 69 String line = in.readLine(); 70 if (echo) { 71 println(line); 72 } 73 return line; 74 } 75 catch (IOException e) { 76 return null; 77 } 78 } 79 80 /** 81 * Read a line (terminated by a newline) from the Terminal. 82 * 83 * @return the string (without the newline character). 84 */ 85 86 public String readLine() 87 { 88 return readLine( "" ); 89 } 90 91 // Read a line from the Terminal. An end of file, 92 // indicated by a null, raises a runtime exception. 93 // Used only internally. 94 95 private String readNonNullLine() 96 { 97 return readNonNullLine( "" ); 98 } 99 100 // Read a line from the Terminal. An end of file, 101 // indicated by a null, raises a runtime exception. 102 // Used only internally. 103 104 private String readNonNullLine( String prompt ) 105 { 106 String line = readLine( prompt ); 107 if (line == null ) { 108 throw new RuntimeException( "End of File encountered." ); 109 } 110 return line; 111 } 112 113 /** 114 * Read a word from the Terminal. 115 * If an empty line is entered, try again. 116 * Words are terminated by whitespace. 117 * Leading whitespace is trimmed; the rest of the line 118 * is disposed of. 119 * 120 * @param prompt output string to prompt for input. 121 * 122 * @return the word read. 123 */ 124 125 public String readWord( String prompt ) 126 { 127 String line = readNonNullLine( prompt ); 128 if (line.length() == 0) { 129 println( "Empty line. Please try again." ); 130 return readWord(""); 131 } 132 line = line.trim(); 133 for ( int i = 0; i < line.length(); i++ ) { 134 if ( Character.isWhitespace( line.charAt(i) ) ) { 135 return line.substring( 0, i ); 136 } 137 } 138 return line; 139 } 140 141 /** 142 * Read a word from the Terminal. 143 * If an empty line is entered, try again. 144 * Words are terminated by whitespace. 145 * Leading whitespace is trimmed; the rest of the line 146 * is disposed of. 147 * 148 * @return the word read. 149 */ 150 151 public String readWord() 152 { 153 return readWord( "" ); 154 } 155 156 /** 157 * Read a word from the Terminal. 158 * If an empty line is entered, throw an exception. 159 * Words are terminated by whitespace. 160 * Leading whitespace is trimmed; the rest of the line 161 * is disposed of. 162 * 163 * @param prompt output string to prompt for input. 164 * @return the word read. 165 * 166 * @throws RuntimeException if it reads an empty line. 167 */ 168 169 public String readWordOnce( String prompt ) 170 { 171 String line = readNonNullLine( prompt ); 172 if (line.length() == 0) { 173 throw new RuntimeException("Empty line encountered."); 174 } 175 line = line.trim(); 176 for ( int i = 0; i < line.length(); i++ ) { 177 if ( Character.isWhitespace( line.charAt(i) ) ) { 178 return line.substring( 0, i ); 179 } 180 } 181 return line; 182 } 183 184 /** 185 * Read a word from the Terminal. 186 * If an empty line is entered, throw an exception. 187 * Words are terminated by whitespace. 188 * Leading whitespace is trimmed; the rest of the line 189 * is disposed of. 190 * 191 * @return the word read. 192 * 193 * @throws RuntimeException if it reads an empty line. 194 */ 195 196 public String readWordOnce() 197 { 198 return readWordOnce( "" ); 199 } 200 201 /** 202 * Read a character from the Terminal. 203 * Prompt again when an empty line is read. 204 * 205 * @param prompt output string to prompt for input. 206 * 207 * @return the character read. 208 */ 209 210 public char readChar( String prompt ) 211 { 212 String line = readNonNullLine(prompt); 213 if (line.length() == 0) { 214 println( "No character on line. Please try again." ); 215 return readChar(""); 216 } 217 return line.charAt(0); 218 } 219 220 /** 221 * Read a character from the Terminal. 222 * Throw an exception if an empty line is read. 223 * 224 * @param prompt output string to prompt for input. 225 * @return the character read. 226 * 227 * @throws RuntimeException if it reads an empty line. 228 */ 229 230 public char readCharOnce( String prompt ) 231 { 232 String line = readNonNullLine(prompt); 233 if (line.length() == 0) { 234 throw new RuntimeException("Empty line encountered."); 235 } 236 return line.charAt(0); 237 } 238 239 /** 240 * Read a character from the Terminal. 241 * Prompt again when an empty line is read. 242 * 243 * 244 * 245 * @return the character read. 246 */ 247 248 public char readChar() 249 { 250 return readChar(""); 251 } 252 253 /** 254 * Read a character from the Terminal. 255 * Throw an exception if an empty line is read. 256 * 257 * @return the character read. 258 * 259 * @throws RuntimeException if it reads an empty line. 260 */ 261 262 public char readCharOnce() 263 { 264 return readCharOnce(""); 265 } 266 267 /** 268 * Read "yes" or "no" from the Terminal. 269 * If an empty line or improper character is read, 270 * try again. 271 * Look only at first character and accept any case. 272 * 273 * @param prompt output string to prompt for input. 274 * @return true if yes, false if no. 275 */ 276 277 public boolean readYesOrNo( String prompt ) 278 { 279 printPrompt( prompt ); 280 while ( true ) { 281 char answer = readChar( " (y or n): "); 282 if ( answer == 'y' || answer == 'Y' ) { 283 return true; 284 } 285 else if ( answer == 'n' || answer == 'N' ) { 286 return false; 287 } 288 else { 289 printPrompt( "oops!" ); 290 } 291 } 292 } 293 294 /** 295 * Read "yes" or "no" from the Terminal. 296 * If an empty line or improper character is read, 297 * throw an exception. 298 * Look only at first character and accept any case. 299 * 300 * @param prompt output string to prompt for input. 301 * @return true if yes, false if no. 302 * 303 * @throws RuntimeException on improper input. 304 */ 305 306 public boolean readYesOrNoOnce( String prompt ) 307 { 308 printPrompt( prompt ); 309 while ( true ) { 310 char answer = readCharOnce( " (y or n): "); 311 if ( answer == 'y' || answer == 'Y' ) { 312 return true; 313 } 314 else if ( answer == 'n' || answer == 'N' ) { 315 return false; 316 } 317 else { 318 throw new RuntimeException( "Must be y or n." ); 319 } 320 } 321 } 322 323 /** 324 * Read "yes" or "no" from the Terminal. 325 * If an empty line or improper character is read, 326 * try again. No prompting is done. 327 * Look only at first character and accept any case. 328 * 329 * @return true if yes, false if no. 330 */ 331 332 public boolean readYesOrNo() 333 { 334 while ( true ) { 335 char answer = readChar(); 336 if ( answer == 'y' || answer == 'Y' ) { 337 return true; 338 } 339 else if ( answer == 'n' || answer == 'N' ) { 340 return false; 341 } 342 } 343 } 344 345 /** 346 * Read "yes" or "no" from the Terminal. 347 * If an empty line or improper character is read, 348 * throw an exception. 349 * Look only at first character and accept any case. 350 * 351 * @return true if yes, false if no. 352 * 353 * @throws RuntimeException on improper input. 354 */ 355 356 public boolean readYesOrNoOnce() 357 { 358 char answer = readCharOnce( " (y or n): "); 359 if ( answer == 'y' || answer == 'Y' ) { 360 return true; 361 } 362 else if ( answer == 'n' || answer == 'N' ) { 363 return false; 364 } 365 else { 366 throw new RuntimeException( "Must be y or n." ); 367 } 368 } 369 370 /** 371 * Read an integer, terminated by a new line, from the Terminal. 372 * If a NumberFormatException is encountered, try again. 373 * 374 * @param prompt output string to prompt for input. 375 * @return the input value as an int. 376 */ 377 378 public int readInt( String prompt ) 379 { 380 while( true ) { 381 try { 382 return Integer. 383 parseInt(readNonNullLine( prompt ).trim()); 384 } 385 catch (NumberFormatException e) { 386 println( "Not an integer. Please try again." ); 387 } 388 } 389 } 390 391 /** 392 * Read an integer, terminated by a new line, from the Terminal. 393 * 394 * @param prompt output string to prompt for input. 395 * @return the input value as an int. 396 * 397 * @throws NumberFormatException for a badly formed integer. 398 */ 399 400 public int readIntOnce( String prompt ) 401 throws NumberFormatException 402 { 403 return Integer.parseInt(readNonNullLine( prompt ).trim()); 404 } 405 406 /** 407 * Read an integer, terminated by a new line, from the Terminal. 408 * If a NumberFormatException is encountered, try again. 409 * 410 * @return the input value as an int. 411 */ 412 413 public int readInt() 414 { 415 return readInt(""); 416 } 417 418 /** 419 * Read an integer, terminated by a new line, from the Terminal. 420 * 421 * @return the input value as an int. 422 * 423 * @throws NumberFormatException for a badly formed integer. 424 */ 425 426 public int readIntOnce() 427 throws NumberFormatException 428 { 429 return readIntOnce(""); 430 } 431 432 /** 433 * Read a double-precision floating point number, 434 * terminated by a newline, from the Terminal. 435 * If a NumberFormatException is encountered, try again. 436 * 437 * @param prompt output string to prompt for input. 438 * @return the input value as a double. 439 */ 440 441 public double readDouble( String prompt ) 442 { 443 while( true ) { 444 try { 445 return Double. 446 parseDouble(readNonNullLine( prompt ).trim()); 447 } 448 catch (NumberFormatException e) { 449 println("Not a floating point number. Please try again."); 450 } 451 } 452 } 453 454 /** 455 * Read a double-precision floating point number, 456 * terminated by a newline, from the Terminal. 457 * 458 * @param prompt output string to prompt for input. 459 * @return the input value as a double. 460 * 461 * @throws NumberFormatException for a badly formed number. 462 */ 463 464 public double readDoubleOnce( String prompt ) 465 throws NumberFormatException 466 { 467 return Double.parseDouble(readNonNullLine( prompt ).trim()); 468 } 469 470 /** 471 * Read a double-precision floating point number, 472 * terminated by a newline, from the Terminal. 473 * If a NumberFormatException is encountered, try again. 474 * 475 * @return the input value as a double. 476 */ 477 478 public double readDouble() 479 { 480 return readDouble(""); 481 } 482 483 /** 484 * Read a double-precision floating point number, 485 * terminated by a newline, from the Terminal. 486 * 487 * @return the input value as a double. 488 * 489 * @throws NumberFormatException for a badly formed number. 490 */ 491 492 public double readDoubleOnce() 493 throws NumberFormatException 494 { 495 return readDouble(""); 496 } 497 498 /** 499 * Print a Boolean value 500 * (<code>true</code> or <code>false</code>) 501 * to standard output (without a newline). 502 * 503 * @param b Boolean to print. 504 */ 505 506 public void print( boolean b ) 507 { 508 System.out.print( b ); 509 } 510 511 /** 512 * Print character to standard output (without a newline). 513 * 514 * @param ch character to print. 515 */ 516 517 public void print( char ch ) 518 { 519 System.out.print( ch ); 520 } 521 522 /** 523 * Print character array to standard output (without a newline). 524 * 525 * @param s character array to print. 526 */ 527 528 public void print( char[] s ) 529 { 530 System.out.print( s ); 531 } 532 533 /** 534 * Print a double-precision floating point number to standard 535 * output (without a newline). 536 * 537 * @param val number to print. 538 */ 539 540 public void print( double val ) 541 { 542 System.out.print( val ); 543 } 544 545 /** 546 * Print a floating point number to standard output 547 * (without a newline). 548 * 549 * @param val number to print. 550 */ 551 552 public void print( float val ) 553 { 554 System.out.print( val ); 555 } 556 557 /** 558 * Print integer to standard output (without a newline). 559 * 560 * @param val integer to print. 561 */ 562 563 public void print( int val ) 564 { 565 System.out.print( val ); 566 } 567 568 /** 569 * Print a long integer to standard output (without a newline). 570 * 571 * @param val integer to print. 572 */ 573 574 public void print( long val ) 575 { 576 System.out.print( val ); 577 } 578 579 /** 580 * Print Object to standard output (without a newline). 581 * 582 * @param val Object to print. 583 */ 584 585 public void print( Object val ) 586 { 587 System.out.print( val.toString() ); 588 } 589 590 /** 591 * Print string to standard output (without a newline). 592 * 593 * @param str String to print. 594 */ 595 596 public void print( String str ) 597 { 598 System.out.print( str ); 599 } 600 601 /** 602 * Print a newline to standard output, 603 * terminating the current line. 604 */ 605 606 public void println() 607 { 608 System.out.println(); 609 } 610 611 /** 612 * Print a Boolean value 613 * (<code>true</code> or <code>false</code>) 614 * to standard output, followed by a newline. 615 * @param b Boolean to print. 616 */ 617 618 public void println( boolean b ) 619 { 620 System.out.println( b ); 621 } 622 623 /** 624 * Print character to standard output, followed by a newline. 625 * 626 * @param ch character to print. 627 */ 628 629 public void println( char ch ) 630 { 631 System.out.println( ch ); 632 } 633 634 /** 635 * Print a character array to standard output, 636 * followed by a newline. 637 * 638 * @param s character array to print. 639 */ 640 641 public void println( char[] s ) 642 { 643 System.out.println( s ); 644 } 645 646 /** 647 * Print floating point number to standard output, 648 * followed by a newline. 649 * 650 * @param val number to print. 651 */ 652 653 public void println( float val ) 654 { 655 System.out.println( val ); 656 } 657 658 /** 659 * Print a double-precision floating point number to standard 660 * output, followed by a newline. 661 * 662 * @param val number to print. 663 */ 664 665 public void println( double val ) 666 { 667 System.out.println( val ); 668 } 669 670 /** 671 * Print integer to standard output, followed by a newline. 672 * 673 * @param val integer to print. 674 */ 675 676 public void println( int val ) 677 { 678 System.out.println( val ); 679 } 680 681 /** 682 * Print a long integer to standard output, 683 * followed by a newline. 684 * 685 * @param val long integer to print. 686 */ 687 688 public void println( long val ) 689 { 690 System.out.println( val ); 691 } 692 693 /** 694 * Print Object to standard output, followed by a newline. 695 * 696 * @param val Object to print 697 */ 698 699 public void println( Object val ) 700 { 701 System.out.println( val.toString() ); 702 } 703 704 /** 705 * Print string to standard output, followed by a newline. 706 * 707 * @param str String to print 708 */ 709 710 public void println( String str ) 711 { 712 System.out.println( str ); 713 } 714 715 /** 716 * Print a Boolean value 717 * (<code>true</code> or <code>false</code>) 718 * to standard err (without a newline). 719 * 720 * @param b Boolean to print. 721 */ 722 723 public void errPrint( boolean b ) 724 { 725 System.err.print( b ); 726 } 727 728 /** 729 * Print character to standard err (without a newline). 730 * 731 * @param ch character to print. 732 */ 733 734 public void errPrint( char ch ) 735 { 736 System.err.print( ch ); 737 } 738 739 /** 740 * Print character array to standard err (without a newline). 741 * 742 * @param s character array to print. 743 */ 744 745 public void errPrint( char[] s ) 746 { 747 System.err.print( s ); 748 } 749 750 /** 751 * Print a double-precision floating point number to standard 752 * err (without a newline). 753 * 754 * @param val number to print. 755 */ 756 757 public void errPrint( double val ) 758 { 759 System.err.print( val ); 760 } 761 762 /** 763 * Print a floating point number to standard err 764 * (without a newline). 765 * 766 * @param val number to print. 767 */ 768 769 public void errPrint( float val ) 770 { 771 System.err.print( val ); 772 } 773 774 /** 775 * Print integer to standard err (without a newline). 776 * 777 * @param val integer to print. 778 */ 779 780 public void errPrint( int val ) 781 { 782 System.err.print( val ); 783 } 784 785 /** 786 * Print a long integer to standard err (without a newline). 787 * 788 * @param val integer to print. 789 */ 790 791 public void errPrint( long val ) 792 { 793 System.err.print( val ); 794 } 795 796 /** 797 * Print Object to standard err (without a newline). 798 * 799 * @param val Object to print. 800 */ 801 802 public void errPrint( Object val ) 803 { 804 System.err.print( val.toString() ); 805 } 806 807 /** 808 * Print string to standard err (without a newline). 809 * 810 * @param str String to print. 811 */ 812 813 public void errPrint( String str ) 814 { 815 System.err.print( str ); 816 } 817 818 /** 819 * Print a newline to standard err, 820 * terminating the current line. 821 */ 822 823 public void errPrintln() 824 { 825 System.err.println(); 826 } 827 828 /** 829 * Print a Boolean value 830 * (<code>true</code> or <code>false</code>) 831 * to standard err, followed by a newline. 832 * 833 * @param b Boolean to print. 834 */ 835 836 public void errPrintln( boolean b ) 837 { 838 System.err.println( b ); 839 } 840 841 /** 842 * Print character to standard err, followed by a newline. 843 * 844 * @param ch character to print. 845 */ 846 847 public void errPrintln( char ch ) 848 { 849 System.err.println( ch ); 850 } 851 852 /** 853 * Print a character array to standard err, 854 * followed by a newline. 855 * 856 * @param s character array to print. 857 */ 858 859 public void errPrintln( char[] s ) 860 { 861 System.err.println( s ); 862 } 863 864 /** 865 * Print floating point number to standard err, 866 * followed by a newline. 867 * 868 * @param val number to print. 869 */ 870 871 public void errPrintln( float val ) 872 { 873 System.err.println( val ); 874 } 875 876 /** 877 * Print a double-precision floating point number to 878 * standard err, followed by a newline. 879 * 880 * @param val number to print. 881 */ 882 883 public void errPrintln( double val ) 884 { 885 System.err.println( val ); 886 } 887 888 /** 889 * Print integer to standard err, followed by a newline. 890 * 891 * @param val integer to print. 892 */ 893 894 public void errPrintln( int val ) 895 { 896 System.err.println( val ); 897 } 898 899 /** 900 * Print a long integer to standard err, followed by a newline. 901 * 902 * @param val long integer to print. 903 */ 904 905 public void errPrintln( long val ) 906 { 907 System.err.println( val ); 908 } 909 910 /** 911 * Print Object to standard err, followed by a newline. 912 * 913 * @param val Object to print 914 */ 915 916 public void errPrintln( Object val ) 917 { 918 System.err.println( val.toString() ); 919 } 920 921 /** 922 * Print string to standard err, followed by a newline. 923 * 924 * @param str String to print 925 */ 926 927 public void errPrintln( String str ) 928 { 929 System.err.println( str ); 930 } 931 932 /** 933 * Unit test for Terminal. 934 * 935 * @param args command line arguments: 936 * <pre> 937 * -e echo all input. 938 * </pre> 939 */ 940 941 public static void main( String[] args ) 942 { 943 Terminal t = 944 new Terminal( args.length == 1 && args[0].equals("-e") ); 945 946 String line = t.readLine( "line:" ); 947 String word = t.readWord( "word:" ); 948 char c = t.readChar( "char:" ); 949 boolean yn = t.readYesOrNo( "yorn:" ); 950 double d = t.readDouble( "double:" ); 951 int i = t.readInt( "int:" ); 952 953 t.print(" line:["); t.print(line); t.print("]"); 954 t.print(" line:["); t.println(line); t.print("]"); 955 956 t.print(" word:["); t.print(word); t.print("]"); 957 t.print(" word:["); t.println(word); t.print("]"); 958 959 t.print(" char:["); t.print(c); t.print("]"); 960 t.print(" char:["); t.println(c); t.print("]"); 961 962 t.print(" yorn:["); t.print(yn); t.print("]"); 963 t.print(" yorn:["); t.println(yn); t.print("]"); 964 965 t.print(" doub:["); t.print(d); t.print("]"); 966 t.print(" doub:["); t.println(d); t.print("]"); 967 968 t.print(" int:["); t.print(i); t.print("]"); 969 t.print(" int:["); t.println(i); t.print("]"); 970 971 t.errPrint(" line:["); t.errPrint(line); t.errPrint("]"); 972 t.errPrint(" line:["); t.errPrintln(line); t.errPrint("]"); 973 974 t.errPrint(" word:["); t.errPrint(word); t.errPrint("]"); 975 t.errPrint(" word:["); t.errPrintln(word); t.errPrint("]"); 976 977 t.errPrint(" char:["); t.errPrint(c); t.errPrint("]"); 978 t.errPrint(" char:["); t.errPrintln(c); t.errPrint("]"); 979 980 t.errPrint(" yorn:["); t.errPrint(yn); t.errPrint("]"); 981 t.errPrint(" yorn:["); t.errPrintln(yn); t.errPrint("]"); 982 983 t.errPrint(" doub:["); t.errPrint(d); t.errPrint("]"); 984 t.errPrint(" doub:["); t.errPrintln(d); t.errPrint("]"); 985 986 t.errPrint(" int:["); t.errPrint(i); t.errPrint("]"); 987 t.errPrint(" int:["); t.errPrintln(i); t.errPrint("]"); 988 } 989 } 990
|
Terminal |
|