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