001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002// The Molly framework is freely distributable under the terms of an
003// MIT-style license. For details, see the molly pages web site at:
004// http://www.mollypages.org/. Use, modify, have fun !
005
006package fc.io;
007
008import java.io.*;
009
010import fc.util.*;
011/**
012Prompts a user for input.
013<p>
014Thread safety: This class is not thread safe and higher level
015synchronization (or multiple instances of this class) should
016be used.
017
018@author hursh jain  
019@version 1.0 12/15/2001
020**/
021public class Prompt 
022{
023      BufferedReader  in; 
024      PrintWriter   err;
025      PrintWriter   out;
026protected   String      line = null; //the current input line
027
028/**
029Constructs the object using the specified input and output writers.
030@param in the BufferedReader to use for input
031@param out  the PrintWriter to use for output
032@param err  the PrintWriter to use for errors
033**/
034public Prompt(Reader in, PrintWriter out, PrintWriter err)
035  {
036  Argcheck.notnull(in); 
037  Argcheck.notnull(out); 
038  Argcheck.notnull(err);
039  this.in = IOUtil.bufferReader(in);
040  this.out = out;
041  this.err = err;
042  }
043
044/**
045Constructs the object using the specified input and output streams.
046@param in the BufferedReader to use for input
047@param out  the PrintWriter to use for output
048@param err  the PrintWriter to use for errors
049**/
050public Prompt(InputStream in, PrintStream out, PrintStream err)
051  {
052  Argcheck.notnull(in); 
053  Argcheck.notnull(out); 
054  Argcheck.notnull(err);
055  this.in = new BufferedReader(new InputStreamReader(in));
056  this.out = new PrintWriter(out);
057  this.err = new PrintWriter(err);
058  }
059
060
061/**
062Constructs a fallback object, using <tt>System.in, System.out</tt>
063for the input, output and error streams.
064**/
065public Prompt()
066  {
067  this( 
068    new BufferedReader(new InputStreamReader(System.in)), 
069    new PrintWriter(System.out), 
070    new PrintWriter(System.err)
071    );
072  }
073
074/**
075Shows the specified string to the user shows the input prompt
076to the user (to indicate the user's input is expected). Keeps
077looping and asking the same question until a non-empty response
078has been typed by the user, then returns that response.
079
080@param  str     the string to show to the user
081@param  newline   whether to print a newline after the string
082*/
083public String ask(String str, boolean newline) 
084  {
085  String result = ""; 
086  while (result.equals("")) 
087    {
088    out.print(str); //the string
089    
090    if (newline)
091      out.println();
092      
093    out.flush();
094    readLine();
095    result = line;
096    }
097
098  return result;
099  }
100
101/**
102Calls {@link ask(String, boolean)} so that a newline
103is not shown after the question shown to the user.
104**/
105public String ask(String str) {
106  return ask(str, false);
107  }
108
109/**
110Shows the specified string to the user shows the input prompt
111to the user (to indicate the user's input is expected). Returns
112the fallback string if a empty response has been typed by the user, 
113else returns the user response.
114
115@param  str     the string to show to the user
116@param  fallback    response to return if the user types in an 
117          empty response (typically by simply hitting a
118          newline)
119@param  newline   whether to print a newline after showing the
120          specified string to the user
121**/
122public String ask(String str, String fallback, boolean newline) 
123  {
124  out.print(str); 
125  if (newline)
126    out.println();
127  
128  out.flush();
129  readLine();
130  if (line.equals(""))
131    return fallback;
132  
133  return line;
134  }
135
136/** 
137Calls {@link ask(String, String, boolean)} so that a newline
138is not shown after the question shown to the user.
139**/
140public String ask(String str, String fallback) {
141  return ask(str, fallback,  false);
142  }
143
144  
145/**
146Immediately writes a string to the output. The prompt is written
147before the string.
148*/
149public void write(String str) 
150  {
151  out.print(str);
152  out.flush();  
153  }
154
155/**
156Immediately writes the specified string as a new line, to the output.
157The prompt is written before the string.
158*/
159public void writeln(String str) 
160  {
161  out.println(str);
162  out.flush();  
163  }
164
165/**
166Gets the latest input line that has been read. Can return the
167same line multiple times if no new lines have been read since
168the last time this method was called. Returns <tt>null</tt>
169if no line has been read so far.
170**/
171public String getLastLine() {
172  return line;
173  }
174
175/**
176Sets the next line of input without the trailing newline
177character. A line of input is signalled when a newline character
178is encountered. This method will block until the input has a 
179newline.<br>
180Note: Unfortunately, as of JDK 1.4 there seems to be no way to
181get the input buffer unless a newline is also entered. (Stream/Reader
182methods like <tt>available</tt> and <tt>ready</tt> return 0/false
183until a newline is entered). This means <tt>System.in</tt> always
184appears to work in "cooked" mode (both on windows and an linux).
185This sucks.
186**/
187protected void readLine() 
188  {
189  try {
190      line = in.readLine();
191    } 
192  catch(java.io.IOException e) {
193    e.printStackTrace();
194    }
195  }
196
197//-- stream/writer sets ----
198
199public void setInput(Reader in) {
200  this.in = IOUtil.bufferReader(in);
201  }
202
203public void setInput(InputStream in) {
204  this.in = new BufferedReader(new InputStreamReader(in)); 
205  }
206
207public void setOutput(PrintStream out) {
208  this.out = new PrintWriter(out);
209  }
210
211public void setOutput(PrintWriter out) {
212  this.out = out;
213  }
214
215public void setError(PrintStream err) {
216  this.err = new PrintWriter(err);
217  }
218
219public void setError(PrintWriter err) {
220  this.err = err;
221  }
222
223
224public static void main(String args[]) throws Exception
225  {
226  new Test(); 
227  }
228
229/** 
230Unit Test History   
231<pre>
232Class Version Tester  Status    Notes
2331.0       hj    passed    
234</pre>
235*/  
236static private class Test 
237{
238Test() throws Exception
239  {
240  Prompt prompt = new Prompt();
241  String name = prompt.ask("What is your name ? ");
242  System.out.println("You entered: " + name);
243  
244  name = prompt.ask("What is your age [default 1] ? ", "1");
245  System.out.println("You entered: " + name);
246  }
247} //~Test
248
249}           //~class Prompt