1 /* 2 * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. 3 * 4 * This software is distributable under the BSD license. See the terms of the 5 * BSD license in the documentation provided with this software. 6 */ 7 package jline; 8 9 import java.io.*; 10 import java.util.*; 11 12 /** 13 * A command history buffer. 14 * 15 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a> 16 */ 17 public class History { 18 19 private List history = new ArrayList(); 20 private PrintWriter output = null; 21 private int maxSize = 500; 22 private int currentIndex = 0; 23 24 /** 25 * Construstor: initialize a blank history. 26 */ History()27 public History() { 28 } 29 30 /** 31 * Construstor: initialize History object the the specified {@link File} for 32 * storage. 33 */ History(final File historyFile)34 public History(final File historyFile) throws IOException { 35 setHistoryFile(historyFile); 36 } 37 setHistoryFile(final File historyFile)38 public void setHistoryFile(final File historyFile) throws IOException { 39 if (historyFile.isFile()) { 40 load(new FileInputStream(historyFile)); 41 } 42 43 setOutput(new PrintWriter(new FileWriter(historyFile), true)); 44 flushBuffer(); 45 } 46 47 /** 48 * Load the history buffer from the specified InputStream. 49 */ load(final InputStream in)50 public void load(final InputStream in) throws IOException { 51 load(new InputStreamReader(in)); 52 } 53 54 /** 55 * Load the history buffer from the specified Reader. 56 */ load(final Reader reader)57 public void load(final Reader reader) throws IOException { 58 BufferedReader breader = new BufferedReader(reader); 59 List lines = new ArrayList(); 60 String line; 61 62 while ((line = breader.readLine()) != null) { 63 lines.add(line); 64 } 65 66 for (Iterator i = lines.iterator(); i.hasNext();) { 67 addToHistory((String) i.next()); 68 } 69 } 70 size()71 public int size() { 72 return history.size(); 73 } 74 75 /** 76 * Clear the history buffer 77 */ clear()78 public void clear() { 79 history.clear(); 80 currentIndex = 0; 81 } 82 83 /** 84 * Add the specified buffer to the end of the history. The pointer is set to 85 * the end of the history buffer. 86 */ addToHistory(final String buffer)87 public void addToHistory(final String buffer) { 88 // don't append duplicates to the end of the buffer 89 if ((history.size() != 0) && buffer.equals(history.get(history.size() - 1))) { 90 return; 91 } 92 93 history.add(buffer); 94 95 while (history.size() > getMaxSize()) { 96 history.remove(0); 97 } 98 99 currentIndex = history.size(); 100 101 if (getOutput() != null) { 102 getOutput().println(buffer); 103 getOutput().flush(); 104 } 105 } 106 107 /** 108 * Flush the entire history buffer to the output PrintWriter. 109 */ flushBuffer()110 public void flushBuffer() throws IOException { 111 if (getOutput() != null) { 112 for (Iterator i = history.iterator(); i.hasNext(); getOutput().println((String) i.next())) { 113 ; 114 } 115 116 getOutput().flush(); 117 } 118 } 119 120 /** 121 * This moves the history to the last entry. This entry is one position 122 * before the moveToEnd() position. 123 * 124 * @return Returns false if there were no history entries or the history 125 * index was already at the last entry. 126 */ moveToLastEntry()127 public boolean moveToLastEntry() { 128 int lastEntry = history.size() - 1; 129 if (lastEntry >= 0 && lastEntry != currentIndex) { 130 currentIndex = history.size() - 1; 131 return true; 132 } 133 134 return false; 135 } 136 137 /** 138 * Move to the end of the history buffer. This will be a blank entry, after 139 * all of the other entries. 140 */ moveToEnd()141 public void moveToEnd() { 142 currentIndex = history.size(); 143 } 144 145 /** 146 * Set the maximum size that the history buffer will store. 147 */ setMaxSize(final int maxSize)148 public void setMaxSize(final int maxSize) { 149 this.maxSize = maxSize; 150 } 151 152 /** 153 * Get the maximum size that the history buffer will store. 154 */ getMaxSize()155 public int getMaxSize() { 156 return this.maxSize; 157 } 158 159 /** 160 * The output to which all history elements will be written (or null of 161 * history is not saved to a buffer). 162 */ setOutput(final PrintWriter output)163 public void setOutput(final PrintWriter output) { 164 this.output = output; 165 } 166 167 /** 168 * Returns the PrintWriter that is used to store history elements. 169 */ getOutput()170 public PrintWriter getOutput() { 171 return this.output; 172 } 173 174 /** 175 * Returns the current history index. 176 */ getCurrentIndex()177 public int getCurrentIndex() { 178 return this.currentIndex; 179 } 180 181 /** 182 * Return the content of the current buffer. 183 */ current()184 public String current() { 185 if (currentIndex >= history.size()) { 186 return ""; 187 } 188 189 return (String) history.get(currentIndex); 190 } 191 192 /** 193 * Move the pointer to the previous element in the buffer. 194 * 195 * @return true if we successfully went to the previous element 196 */ previous()197 public boolean previous() { 198 if (currentIndex <= 0) { 199 return false; 200 } 201 202 currentIndex--; 203 204 return true; 205 } 206 207 /** 208 * Move the pointer to the next element in the buffer. 209 * 210 * @return true if we successfully went to the next element 211 */ next()212 public boolean next() { 213 if (currentIndex >= history.size()) { 214 return false; 215 } 216 217 currentIndex++; 218 219 return true; 220 } 221 222 /** 223 * Returns an immutable list of the history buffer. 224 */ getHistoryList()225 public List getHistoryList() { 226 return Collections.unmodifiableList(history); 227 } 228 229 /** 230 * Returns the standard {@link AbstractCollection#toString} representation 231 * of the history list. 232 */ toString()233 public String toString() { 234 return history.toString(); 235 } 236 237 /** 238 * Moves the history index to the first entry. 239 * 240 * @return Return false if there are no entries in the history or if the 241 * history is already at the beginning. 242 */ moveToFirstEntry()243 public boolean moveToFirstEntry() { 244 if (history.size() > 0 && currentIndex != 0) { 245 currentIndex = 0; 246 return true; 247 } 248 249 return false; 250 } 251 252 /** 253 * Search backward in history from a given position. 254 * 255 * @param searchTerm substring to search for. 256 * @param startIndex the index from which on to search 257 * @return index where this substring has been found, or -1 else. 258 */ searchBackwards(String searchTerm, int startIndex)259 public int searchBackwards(String searchTerm, int startIndex) { 260 for (int i = startIndex - 1; i >= 0; i--) { 261 if (i >= size()) 262 continue; 263 if (getHistory(i).indexOf(searchTerm) != -1) { 264 return i; 265 } 266 } 267 return -1; 268 } 269 270 /** 271 * Search backwards in history from the current position. 272 * 273 * @param searchTerm substring to search for. 274 * @return index where the substring has been found, or -1 else. 275 */ searchBackwards(String s)276 public int searchBackwards(String s) { 277 return searchBackwards(s, getCurrentIndex()); 278 } 279 280 /** 281 * Get the history string for the given index. 282 * 283 * @param index 284 * @return 285 */ getHistory(int index)286 public String getHistory(int index) { 287 return (String) history.get(index); 288 } 289 290 /** 291 * Set current index to given number. 292 * 293 * @param index 294 */ setCurrentIndex(int index)295 public void setCurrentIndex(int index) { 296 if (index >= 0 && index < history.size()) 297 currentIndex = index; 298 } 299 } 300