001 /*
002 * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
003 *
004 * This software is distributable under the BSD license. See the terms of the
005 * BSD license in the documentation provided with this software.
006 */
007 package jline;
008
009 import java.io.*;
010 import java.util.*;
011
012 /**
013 * A command history buffer.
014 *
015 * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
016 */
017 public class History {
018 private List history = new ArrayList();
019
020 private PrintWriter output = null;
021
022 private int maxSize = 500;
023
024 private int currentIndex = 0;
025
026 /**
027 * Construstor: initialize a blank history.
028 */
029 public History() {
030 }
031
032 /**
033 * Construstor: initialize History object the the specified {@link File} for
034 * storage.
035 */
036 public History(final File historyFile) throws IOException {
037 setHistoryFile(historyFile);
038 }
039
040 public void setHistoryFile(final File historyFile) throws IOException {
041 if (historyFile.isFile()) {
042 load(new FileInputStream(historyFile));
043 }
044
045 setOutput(new PrintWriter(new FileWriter(historyFile), true));
046 flushBuffer();
047 }
048
049 /**
050 * Load the history buffer from the specified InputStream.
051 */
052 public void load(final InputStream in) throws IOException {
053 load(new InputStreamReader(in));
054 }
055
056 /**
057 * Load the history buffer from the specified Reader.
058 */
059 public void load(final Reader reader) throws IOException {
060 BufferedReader breader = new BufferedReader(reader);
061 List lines = new ArrayList();
062 String line;
063
064 while ((line = breader.readLine()) != null) {
065 lines.add(line);
066 }
067
068 for (Iterator i = lines.iterator(); i.hasNext();) {
069 addToHistory((String) i.next());
070 }
071 }
072
073 public int size() {
074 return history.size();
075 }
076
077 /**
078 * Clear the history buffer
079 */
080 public void clear() {
081 history.clear();
082 currentIndex = 0;
083 }
084
085 /**
086 * Add the specified buffer to the end of the history. The pointer is set to
087 * the end of the history buffer.
088 */
089 public void addToHistory(final String buffer) {
090 // don't append duplicates to the end of the buffer
091 if ((history.size() != 0)
092 && buffer.equals(history.get(history.size() - 1))) {
093 return;
094 }
095
096 history.add(buffer);
097
098 while (history.size() > getMaxSize()) {
099 history.remove(0);
100 }
101
102 currentIndex = history.size();
103
104 if (getOutput() != null) {
105 getOutput().println(buffer);
106 getOutput().flush();
107 }
108 }
109
110 /**
111 * Flush the entire history buffer to the output PrintWriter.
112 */
113 public void flushBuffer() throws IOException {
114 if (getOutput() != null) {
115 for (Iterator i = history.iterator(); i.hasNext(); getOutput()
116 .println((String) i.next())) {
117 ;
118 }
119
120 getOutput().flush();
121 }
122 }
123
124 /**
125 * This moves the history to the last entry. This entry is one position
126 * before the moveToEnd() position.
127 *
128 * @return Returns false if there were no history entries or the history
129 * index was already at the last entry.
130 */
131 public boolean moveToLastEntry() {
132 int lastEntry = history.size() - 1;
133 if (lastEntry >= 0 && lastEntry != currentIndex) {
134 currentIndex = history.size() - 1;
135 return true;
136 }
137
138 return false;
139 }
140
141 /**
142 * Move to the end of the history buffer. This will be a blank entry, after
143 * all of the other entries.
144 */
145 public void moveToEnd() {
146 currentIndex = history.size();
147 }
148
149 /**
150 * Set the maximum size that the history buffer will store.
151 */
152 public void setMaxSize(final int maxSize) {
153 this.maxSize = maxSize;
154 }
155
156 /**
157 * Get the maximum size that the history buffer will store.
158 */
159 public int getMaxSize() {
160 return this.maxSize;
161 }
162
163 /**
164 * The output to which all history elements will be written (or null of
165 * history is not saved to a buffer).
166 */
167 public void setOutput(final PrintWriter output) {
168 this.output = output;
169 }
170
171 /**
172 * Returns the PrintWriter that is used to store history elements.
173 */
174 public PrintWriter getOutput() {
175 return this.output;
176 }
177
178 /**
179 * Returns the current history index.
180 */
181 public int getCurrentIndex() {
182 return this.currentIndex;
183 }
184
185 /**
186 * Return the content of the current buffer.
187 */
188 public String current() {
189 if (currentIndex >= history.size()) {
190 return "";
191 }
192
193 return (String) history.get(currentIndex);
194 }
195
196 /**
197 * Move the pointer to the previous element in the buffer.
198 *
199 * @return true if we successfully went to the previous element
200 */
201 public boolean previous() {
202 if (currentIndex <= 0) {
203 return false;
204 }
205
206 currentIndex--;
207
208 return true;
209 }
210
211 /**
212 * Move the pointer to the next element in the buffer.
213 *
214 * @return true if we successfully went to the next element
215 */
216 public boolean next() {
217 if (currentIndex >= history.size()) {
218 return false;
219 }
220
221 currentIndex++;
222
223 return true;
224 }
225
226 /**
227 * Returns an immutable list of the history buffer.
228 */
229 public List getHistoryList() {
230 return Collections.unmodifiableList(history);
231 }
232
233 /**
234 * Returns the standard {@link AbstractCollection#toString} representation
235 * of the history list.
236 */
237 public String toString() {
238 return history.toString();
239 }
240
241 /**
242 * Moves the history index to the first entry.
243 *
244 * @return Return false if there are no entries in the history or if the
245 * history is already at the beginning.
246 */
247 public boolean moveToFirstEntry() {
248 if (history.size() > 0 && currentIndex != 0) {
249 currentIndex = 0;
250 return true;
251 }
252
253 return false;
254 }
255 }