001    /**
002     *      jline - Java console input library
003     *      Copyright (c) 2002-2006, Marc Prud'hommeaux <mwp1@cornell.edu>
004     *      All rights reserved.
005     *
006     *      Redistribution and use in source and binary forms, with or
007     *      without modification, are permitted provided that the following
008     *      conditions are met:
009     *
010     *      Redistributions of source code must retain the above copyright
011     *      notice, this list of conditions and the following disclaimer.
012     *
013     *      Redistributions in binary form must reproduce the above copyright
014     *      notice, this list of conditions and the following disclaimer
015     *      in the documentation and/or other materials provided with
016     *      the distribution.
017     *
018     *      Neither the name of JLine nor the names of its contributors
019     *      may be used to endorse or promote products derived from this
020     *      software without specific prior written permission.
021     *
022     *      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
023     *      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
024     *      BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
025     *      AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
026     *      EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
027     *      FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
028     *      OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
029     *      PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
030     *      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
031     *      AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
032     *      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
033     *      IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
034     *      OF THE POSSIBILITY OF SUCH DAMAGE.
035     */
036    package jline;
037    
038    import java.io.*;
039    import java.util.*;
040    
041    
042    /**
043     *  A command history buffer.
044     *
045     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
046     */
047    public class History
048    {
049            private List                    history                 = new ArrayList ();
050            private PrintWriter             output                  = null;
051            private int                             maxSize                 = 500;
052            private int                             currentIndex    = 0;
053    
054    
055            /**
056             *  Construstor: initialize a blank history.
057             */
058            public History ()
059            {
060            }
061    
062    
063            /**
064             *  Construstor: initialize History object the the specified
065             *  {@link File} for storage.
066             */
067            public History (final File historyFile)
068                    throws IOException
069            {
070                    setHistoryFile (historyFile);
071            }
072    
073    
074            public void setHistoryFile (final File historyFile)
075                    throws IOException
076            {
077                    if (historyFile.isFile ())
078                            load (new FileInputStream (historyFile));
079                    setOutput (new PrintWriter (new FileWriter (historyFile), true));
080                    flushBuffer ();
081            }
082    
083    
084            /**
085             *  Load the history buffer from the specified InputStream.
086             */
087            public void load (final InputStream in)
088                    throws IOException
089            {
090                    load (new InputStreamReader (in));
091            }
092    
093    
094            /**
095             *  Load the history buffer from the specified Reader.
096             */
097            public void load (final Reader reader)
098                    throws IOException
099            {
100                    BufferedReader breader = new BufferedReader (reader);
101                    List lines = new ArrayList ();
102                    String line;
103                    while ((line = breader.readLine ()) != null)
104                    {
105                            lines.add (line);
106                    }
107    
108                    for (Iterator i = lines.iterator (); i.hasNext (); )
109                            addToHistory ((String)i.next ());
110            }
111    
112    
113            public int size ()
114            {
115                    return history.size ();
116            }
117    
118    
119            /**
120             *  Clear the history buffer
121             */
122            public void clear ()
123            {
124                    history.clear ();
125                    currentIndex = 0;
126            }
127    
128    
129            /**
130             *  Add the specified buffer to the end of the history. The pointer is
131             *  set to the end of the history buffer.
132             */
133            public void addToHistory (final String buffer)
134            {
135                    // don't append duplicates to the end of the buffer
136                    if (history.size () != 0 && buffer.equals (
137                            history.get (history.size () - 1)))
138                            return;
139    
140                    history.add (buffer);
141                    while (history.size () > getMaxSize ())
142                            history.remove (0);
143    
144                    currentIndex = history.size ();
145    
146                    if (getOutput () != null)
147                    {
148                            getOutput ().println (buffer);
149                            getOutput ().flush ();
150                    }
151            }
152    
153    
154            /**
155             *  Flush the entire history buffer to the output PrintWriter.
156             */
157            public void flushBuffer ()
158                    throws IOException
159            {
160                    if (getOutput () != null)
161                    {
162                            for (Iterator i = history.iterator (); i.hasNext ();
163                                    getOutput ().println ((String)i.next ()));
164    
165                            getOutput ().flush ();
166                    }
167            }
168    
169    
170            /**
171             *  Move to the end of the history buffer.
172             */
173            public void moveToEnd ()
174            {
175                    currentIndex = history.size ();
176            }
177    
178    
179            /**
180             *  Set the maximum size that the history buffer will store.
181             */
182            public void setMaxSize (final int maxSize)
183            {
184                    this.maxSize = maxSize;
185            }
186    
187    
188            /**
189             *  Get the maximum size that the history buffer will store.
190             */
191            public int getMaxSize ()
192            {
193                    return this.maxSize;
194            }
195    
196    
197            /**
198             *  The output to which all history elements will be written (or null
199             *  of history is not saved to a buffer).
200             */
201            public void setOutput (final PrintWriter output)
202            {
203                    this.output = output;
204            }
205    
206    
207            /**
208             *  Returns the PrintWriter that is used to store history elements.
209             */
210            public PrintWriter getOutput ()
211            {
212                    return this.output;
213            }
214    
215    
216            /**
217             *  Returns the current history index.
218             */
219            public int getCurrentIndex ()
220            {
221                    return this.currentIndex;
222            }
223    
224    
225            /**
226             *  Return the content of the current buffer.
227             */
228            public String current ()
229            {
230                    if (currentIndex >= history.size ())
231                            return "";
232    
233                    return (String)history.get (currentIndex);
234            }
235    
236    
237            /**
238             *  Move the pointer to the previous element in the buffer.
239             *
240             *  @return  true if we successfully went to the previous element
241             */
242            public boolean previous ()
243            {
244                    if (currentIndex <= 0)
245                            return false;
246    
247                    currentIndex--;
248                    return true;
249            }
250    
251    
252            /**
253             *  Move the pointer to the next element in the buffer.
254             *
255             *  @return  true if we successfully went to the next element
256             */
257            public boolean next ()
258            {
259                    if (currentIndex >= history.size ())
260                            return false;
261    
262                    currentIndex++;
263                    return true;
264            }
265    
266    
267            /**
268             *  Returns an immutable list of the history buffer.
269             */
270            public List getHistoryList ()
271            {
272                    return Collections.unmodifiableList (history);
273            }
274    
275    
276            /**
277             *  Returns the standard {@link AbstractCollection#toString} representation
278             *  of the history list.
279             */
280            public String toString ()
281            {
282                    return history.toString ();
283            }
284    }
285