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