001    /*
002     * Copyright (c) 2002-2006, 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        private PrintWriter output = null;
020        private int maxSize = 500;
021        private int currentIndex = 0;
022    
023        /**
024         *  Construstor: initialize a blank history.
025         */
026        public History() {
027        }
028    
029        /**
030         *  Construstor: initialize History object the the specified
031         *  {@link File} for storage.
032         */
033        public History(final File historyFile) throws IOException {
034            setHistoryFile(historyFile);
035        }
036    
037        public void setHistoryFile(final File historyFile)
038                            throws IOException {
039            if (historyFile.isFile()) {
040                load(new FileInputStream(historyFile));
041            }
042    
043            setOutput(new PrintWriter(new FileWriter(historyFile), true));
044            flushBuffer();
045        }
046    
047        /**
048         *  Load the history buffer from the specified InputStream.
049         */
050        public void load(final InputStream in) throws IOException {
051            load(new InputStreamReader(in));
052        }
053    
054        /**
055         *  Load the history buffer from the specified Reader.
056         */
057        public void load(final Reader reader) throws IOException {
058            BufferedReader breader = new BufferedReader(reader);
059            List lines = new ArrayList();
060            String line;
061    
062            while ((line = breader.readLine()) != null) {
063                lines.add(line);
064            }
065    
066            for (Iterator i = lines.iterator(); i.hasNext();) {
067                addToHistory((String) i.next());
068            }
069        }
070    
071        public int size() {
072            return history.size();
073        }
074    
075        /**
076         *  Clear the history buffer
077         */
078        public void clear() {
079            history.clear();
080            currentIndex = 0;
081        }
082    
083        /**
084         *  Add the specified buffer to the end of the history. The pointer is
085         *  set to the end of the history buffer.
086         */
087        public void addToHistory(final String buffer) {
088            // don't append duplicates to the end of the buffer
089            if ((history.size() != 0)
090                    && buffer.equals(history.get(history.size() - 1))) {
091                return;
092            }
093    
094            history.add(buffer);
095    
096            while (history.size() > getMaxSize()) {
097                history.remove(0);
098            }
099    
100            currentIndex = history.size();
101    
102            if (getOutput() != null) {
103                getOutput().println(buffer);
104                getOutput().flush();
105            }
106        }
107    
108        /**
109         *  Flush the entire history buffer to the output PrintWriter.
110         */
111        public void flushBuffer() throws IOException {
112            if (getOutput() != null) {
113                for (Iterator i = history.iterator(); i.hasNext();
114                         getOutput().println((String) i.next())) {
115                    ;
116                }
117    
118                getOutput().flush();
119            }
120        }
121    
122        /**
123         *  Move to the end of the history buffer.
124         */
125        public void moveToEnd() {
126            currentIndex = history.size();
127        }
128    
129        /**
130         *  Set the maximum size that the history buffer will store.
131         */
132        public void setMaxSize(final int maxSize) {
133            this.maxSize = maxSize;
134        }
135    
136        /**
137         *  Get the maximum size that the history buffer will store.
138         */
139        public int getMaxSize() {
140            return this.maxSize;
141        }
142    
143        /**
144         *  The output to which all history elements will be written (or null
145         *  of history is not saved to a buffer).
146         */
147        public void setOutput(final PrintWriter output) {
148            this.output = output;
149        }
150    
151        /**
152         *  Returns the PrintWriter that is used to store history elements.
153         */
154        public PrintWriter getOutput() {
155            return this.output;
156        }
157    
158        /**
159         *  Returns the current history index.
160         */
161        public int getCurrentIndex() {
162            return this.currentIndex;
163        }
164    
165        /**
166         *  Return the content of the current buffer.
167         */
168        public String current() {
169            if (currentIndex >= history.size()) {
170                return "";
171            }
172    
173            return (String) history.get(currentIndex);
174        }
175    
176        /**
177         *  Move the pointer to the previous element in the buffer.
178         *
179         *  @return  true if we successfully went to the previous element
180         */
181        public boolean previous() {
182            if (currentIndex <= 0) {
183                return false;
184            }
185    
186            currentIndex--;
187    
188            return true;
189        }
190    
191        /**
192         *  Move the pointer to the next element in the buffer.
193         *
194         *  @return  true if we successfully went to the next element
195         */
196        public boolean next() {
197            if (currentIndex >= history.size()) {
198                return false;
199            }
200    
201            currentIndex++;
202    
203            return true;
204        }
205    
206        /**
207         *  Returns an immutable list of the history buffer.
208         */
209        public List getHistoryList() {
210            return Collections.unmodifiableList(history);
211        }
212    
213        /**
214         *  Returns the standard {@link AbstractCollection#toString} representation
215         *  of the history list.
216         */
217        public String toString() {
218            return history.toString();
219        }
220    }