/******************************************************************************
* Copyright (C) 2013 Jonah Graham
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jonah Graham <jonah@kichwacoders.com> - initial API and implementation
******************************************************************************/
package org.python.pydev.shared_interactive_console.console;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.preference.IPreferenceStore;
import org.python.pydev.shared_core.SharedCorePlugin;
import org.python.pydev.shared_core.log.Log;
import org.python.pydev.shared_core.structure.LinkedListWarningOnSlowOperations;
import org.python.pydev.shared_interactive_console.InteractiveConsolePlugin;
import org.python.pydev.shared_interactive_console.console.ui.ScriptConsoleUIConstants;
/**
* Storage wrapper for the global history for the interactive console.
*/
public enum ScriptConsoleGlobalHistory {
/** The singleton instance to use */
INSTANCE;
private static final String HISTORY_PY = "history.py";
private final LinkedList<String> lines;
private ScriptConsoleGlobalHistory() {
lines = new LinkedListWarningOnSlowOperations<String>();
load();
}
/**
* Get the current contents of the global history.
* @return a copy of the history. The returned value can be modified.
*/
public synchronized List<String> get() {
return new ArrayList<String>(lines);
}
/**
* Append and store some new history.
* @param history to store
*/
public synchronized void append(List<String> history) {
int historyMaxEntries = getHistoryMaxEntries();
if (history.size() > historyMaxEntries) {
//Get only the last entries
history = history.subList(history.size() - historyMaxEntries, history.size());
}
if (history.size() >= historyMaxEntries) {
lines.clear(); //We already know the current history will be larger than the available space
}
for (String line : history) {
lines.add(line);
}
//If we ended with more than we could, remove the additional entries (using a LinkedList so that this can be fast).
while (lines.size() > historyMaxEntries) {
lines.removeFirst();
}
store();
}
/**
* Erase and store the global history.
*/
public synchronized void clear() {
lines.clear();
store();
}
private synchronized void load() {
File history = getHistoryFile();
if (history != null) {
try {
BufferedReader br = new BufferedReader(new FileReader(history));
try {
String line = br.readLine();
while (line != null) {
lines.add(line);
line = br.readLine();
}
} catch (IOException e) {
Log.log("Failed reading existing console history.py", e);
} finally {
try {
br.close();
} catch (IOException e) {
Log.log("Failed closing existing console history.py", e);
}
}
} catch (FileNotFoundException e) {
Log.logInfo("No existing console history at: " + history, e);
}
}
}
private synchronized void store() {
File history = getHistoryFile();
if (history != null) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(history));
try {
for (String line : lines) {
bw.write(line);
bw.write("\n");
}
} catch (IOException e) {
Log.log("Failed writing console history.py", e);
} finally {
try {
bw.close();
} catch (IOException e) {
Log.log("Failed closing console history.py", e);
}
}
} catch (IOException e) {
Log.log("Failed creating console history.py", e);
}
}
}
private int getHistoryMaxEntries() {
if (SharedCorePlugin.inTestMode()) {
return ScriptConsoleUIConstants.DEFAULT_INTERACTIVE_CONSOLE_PERSISTENT_HISTORY_MAXIMUM_ENTRIES;
}
InteractiveConsolePlugin plugin = InteractiveConsolePlugin.getDefault();
IPreferenceStore store = plugin.getPreferenceStore();
int historyMaxEntries = store
.getInt(ScriptConsoleUIConstants.INTERACTIVE_CONSOLE_PERSISTENT_HISTORY_MAXIMUM_ENTRIES);
if (historyMaxEntries < 0) {
historyMaxEntries = 0;
}
return historyMaxEntries;
}
private File getHistoryFile() {
if (SharedCorePlugin.inTestMode()) {
return null;
}
InteractiveConsolePlugin plugin = InteractiveConsolePlugin.getDefault();
IPath location = plugin.getStateLocation();
IPath path = location.append(HISTORY_PY);
return path.toFile();
}
}