|
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 |
|