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