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    
006    package fc.io;
007    
008    import java.io.*;
009    
010    import fc.util.*;
011    /**
012    Prompts a user for input.
013    <p>
014    Thread safety: This class is not thread safe and higher level
015    synchronization (or multiple instances of this class) should
016    be used.
017    
018    @author hursh jain  
019    @version 1.0 12/15/2001
020    **/
021    public class Prompt 
022    {
023          BufferedReader  in; 
024          PrintWriter   err;
025          PrintWriter   out;
026    protected   String      line = null; //the current input line
027    
028    /**
029    Constructs 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    **/
034    public 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    /**
045    Constructs 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    **/
050    public 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    /**
062    Constructs a fallback object, using <tt>System.in, System.out</tt>
063    for the input, output and error streams.
064    **/
065    public 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    /**
075    Shows the specified string to the user shows the input prompt
076    to the user (to indicate the user's input is expected). Keeps
077    looping and asking the same question until a non-empty response
078    has 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    */
083    public 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    /**
102    Calls {@link ask(String, boolean)} so that a newline
103    is not shown after the question shown to the user.
104    **/
105    public String ask(String str) {
106      return ask(str, false);
107      }
108    
109    /**
110    Shows the specified string to the user shows the input prompt
111    to the user (to indicate the user's input is expected). Returns
112    the fallback string if a empty response has been typed by the user, 
113    else 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    **/
122    public 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    /** 
137    Calls {@link ask(String, String, boolean)} so that a newline
138    is not shown after the question shown to the user.
139    **/
140    public String ask(String str, String fallback) {
141      return ask(str, fallback,  false);
142      }
143    
144      
145    /**
146    Immediately writes a string to the output. The prompt is written
147    before the string.
148    */
149    public void write(String str) 
150      {
151      out.print(str);
152      out.flush();  
153      }
154    
155    /**
156    Immediately writes the specified string as a new line, to the output.
157    The prompt is written before the string.
158    */
159    public void writeln(String str) 
160      {
161      out.println(str);
162      out.flush();  
163      }
164    
165    /**
166    Gets the latest input line that has been read. Can return the
167    same line multiple times if no new lines have been read since
168    the last time this method was called. Returns <tt>null</tt>
169    if no line has been read so far.
170    **/
171    public String getLastLine() {
172      return line;
173      }
174    
175    /**
176    Sets the next line of input without the trailing newline
177    character. A line of input is signalled when a newline character
178    is encountered. This method will block until the input has a 
179    newline.<br>
180    Note: Unfortunately, as of JDK 1.4 there seems to be no way to
181    get the input buffer unless a newline is also entered. (Stream/Reader
182    methods like <tt>available</tt> and <tt>ready</tt> return 0/false
183    until a newline is entered). This means <tt>System.in</tt> always
184    appears to work in "cooked" mode (both on windows and an linux).
185    This sucks.
186    **/
187    protected 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    
199    public void setInput(Reader in) {
200      this.in = IOUtil.bufferReader(in);
201      }
202    
203    public void setInput(InputStream in) {
204      this.in = new BufferedReader(new InputStreamReader(in)); 
205      }
206    
207    public void setOutput(PrintStream out) {
208      this.out = new PrintWriter(out);
209      }
210    
211    public void setOutput(PrintWriter out) {
212      this.out = out;
213      }
214    
215    public void setError(PrintStream err) {
216      this.err = new PrintWriter(err);
217      }
218    
219    public void setError(PrintWriter err) {
220      this.err = err;
221      }
222    
223    
224    public static void main(String args[]) throws Exception
225      {
226      new Test(); 
227      }
228    
229    /** 
230    Unit Test History   
231    <pre>
232    Class Version Tester  Status    Notes
233    1.0       hj    passed    
234    </pre>
235    */  
236    static private class Test 
237    {
238    Test() 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