blob: 272564672bb882e7b3ccc0c007f06a3a023e8cf2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation and others.
* 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
*
*******************************************************************************/
package org.eclipse.dltk.console.ui;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.dltk.console.IScriptInterpreter;
import org.eclipse.dltk.console.ScriptConsoleHistory;
import org.eclipse.dltk.console.ScriptConsolePrompt;
import org.eclipse.dltk.console.ui.internal.ICommandHandler;
import org.eclipse.dltk.console.ui.internal.ScriptConsoleInput;
import org.eclipse.dltk.console.ui.internal.ScriptConsolePage;
import org.eclipse.dltk.console.ui.internal.ScriptConsoleSession;
import org.eclipse.dltk.console.ui.internal.ScriptConsoleViewer;
import org.eclipse.dltk.console.ui.internal.ScriptConsoleViewer.ConsoleDocumentListener;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.IConsoleDocumentPartitioner;
import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.console.TextConsole;
import org.eclipse.ui.part.IPageBookViewPage;
public class ScriptConsole extends TextConsole implements ICommandHandler {
private final class InitialStreamReader implements Runnable {
private final IScriptInterpreter interpreter;
private InitialStreamReader(IScriptInterpreter interpreter) {
this.interpreter = interpreter;
}
public void run() {
// We need to be sure what page is already created
while (page == null) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
final ScriptConsoleViewer viewer = (ScriptConsoleViewer) page
.getViewer();
InputStream stream = interpreter.getInitialOutputStream();
if (stream == null) {
return;
}
final BufferedReader reader = new BufferedReader(
new InputStreamReader(stream));
Thread readerThread = new Thread(new Runnable() {
public void run() {
boolean first = true;
while (!terminated) {
String readLine;
try {
readLine = reader.readLine();
if (readLine != null) {
updateText(viewer, readLine, first);
first = false;
} else {
break;
}
} catch (IOException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
break;
}
}
if (!first) {
appendInvitation(viewer);
}
}
});
readerThread.start();
}
private void appendInvitation(final ScriptConsoleViewer viewer) {
Control control = viewer.getControl();
if (control == null) {
return;
}
control.getDisplay().asyncExec(new Runnable() {
public void run() {
try {
viewer.disableProcessing();
getDocumentListener().appendDelimeter();
getDocumentListener().appendInvitation();
viewer.enableProcessing();
} catch (BadLocationException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
});
}
private void updateText(final ScriptConsoleViewer viewer,
final String text, final boolean clean) {
Control control = viewer.getControl();
if (control == null) {
return;
}
control.getDisplay().asyncExec(new Runnable() {
public void run() {
viewer.disableProcessing();
IDocument document = getDocument();
try {
if (clean) {
document.replace(0, document.getLength(), text);
getDocumentListener().appendDelimeter();
} else {
document.replace(document.getLength(), 0, text);
getDocumentListener().appendDelimeter();
}
IDocumentPartitioner partitioner = viewer.getDocument()
.getDocumentPartitioner();
if (partitioner instanceof ScriptConsolePartitioner) {
ScriptConsolePartitioner scriptConsolePartitioner = (ScriptConsolePartitioner) partitioner;
scriptConsolePartitioner.clearRanges();
viewer.getTextWidget().redraw();
}
} catch (BadLocationException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
viewer.enableProcessing();
}
});
}
}
protected ScriptConsolePage page;
private ScriptConsolePartitioner partitioner;
private IContentAssistProcessor processor;
private ITextHover hover;
private IScriptInterpreter interpreter;
private ScriptConsoleSession session;
private ListenerList consoleListeners;
private ScriptConsolePrompt prompt;
private ScriptConsoleHistory history;
private IConsoleStyleProvider styleProvider;
private boolean terminated = false;
private Color colorBlack = new Color(Display.getCurrent(), new RGB(0, 0, 0));
private Color colorBlue = new Color(Display.getCurrent(),
new RGB(0, 0, 255));
private Color colorRed = new Color(Display.getCurrent(), new RGB(255, 0, 0));
protected IConsoleDocumentPartitioner getPartitioner() {
return partitioner;
}
public ScriptConsole(String consoleName, String consoleType,
ImageDescriptor image) {
super(consoleName, consoleType, image, true);
this.consoleListeners = new ListenerList(ListenerList.IDENTITY);
this.prompt = new ScriptConsolePrompt("=>", "->"); //$NON-NLS-1$ //$NON-NLS-2$
this.history = new ScriptConsoleHistory();
this.session = new ScriptConsoleSession();
addListener(this.session);
partitioner = new ScriptConsolePartitioner();
getDocument().setDocumentPartitioner(partitioner);
partitioner.connect(getDocument());
styleProvider = new IConsoleStyleProvider() {
protected StyleRange[] createStyles(int start, String content,
boolean isInput, boolean isError) {
List rangeList = new ArrayList();
if ((colorBlack.isDisposed() != true)
&& (colorRed.isDisposed() != true)
&& (colorBlue.isDisposed() != true)) {
// Content has to be tokenized in order for style and
// hyperlinks to display correctly
StringTokenizer tokenizer = new StringTokenizer(content,
" \t\n\r\f@#=|,()[]{}<>'\"", true); //$NON-NLS-1$
String token;
int tokenStart = start;
while (tokenizer.hasMoreTokens() == true) {
token = tokenizer.nextToken();
if (isInput == true) {
rangeList.add(new StyleRange(tokenStart, token
.length(), colorBlack, null, SWT.BOLD));
} else {
if (isError == true) {
rangeList.add(new StyleRange(tokenStart, token
.length(), colorRed, null, SWT.BOLD));
} else {
rangeList.add(new StyleRange(tokenStart, token
.length(), colorBlue, null));
}
}
tokenStart += token.length();
}
}
return (StyleRange[]) rangeList
.toArray(new StyleRange[rangeList.size()]);
}
public StyleRange[] createPromptStyle(ScriptConsolePrompt prompt,
int offset) {
return createStyles(offset, prompt.toString(), true, false);
}
public StyleRange[] createUserInputStyle(String content, int offset) {
return createStyles(offset, content, true, false);
}
public StyleRange[] createInterpreterOutputStyle(String content,
int offset) {
return createStyles(offset, content, false, false);
}
};
}
public ScriptConsole(String consoleName, String consoleType) {
this(consoleName, consoleType, null);
}
public IScriptConsoleSession getSession() {
return session;
}
public void addListener(IScriptConsoleListener listener) {
consoleListeners.add(listener);
}
public void removeListener(IScriptConsoleListener listener) {
consoleListeners.remove(listener);
}
protected void setContentAssistProcessor(IContentAssistProcessor processor) {
this.processor = processor;
}
protected void setInterpreter(final IScriptInterpreter interpreter) {
this.interpreter = interpreter;
interpreter.addInitialListenerOperation(new InitialStreamReader(
interpreter));
}
protected void setStyleProvider(IConsoleStyleProvider provider) {
this.styleProvider = provider;
}
public void setPrompt(ScriptConsolePrompt prompt) {
this.prompt = prompt;
}
public ScriptConsolePrompt getPrompt() {
return prompt;
}
public ScriptConsoleHistory getHistory() {
return history;
}
protected void setTextHover(ITextHover hover) {
this.hover = hover;
}
private ConsoleDocumentListener documentListener;
public ConsoleDocumentListener getDocumentListener() {
if (documentListener == null) {
documentListener = new ConsoleDocumentListener(this, this
.getPrompt(), this.getHistory());
documentListener.setDocument(getDocument());
}
return documentListener;
}
public IPageBookViewPage createPage(IConsoleView view) {
SourceViewerConfiguration cfg = new ScriptConsoleSourceViewerConfiguration(
processor, hover);
page = new ScriptConsolePage(this, view, cfg);
if (styleProvider != null)
page.setStyleProviser(styleProvider);
return page;
}
public void clearConsole() {
page.clearConsolePage();
}
public IScriptConsoleInput getInput() {
return new ScriptConsoleInput(page);
}
public String handleCommand(String userInput) throws IOException {
Object[] listeners = consoleListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
((IScriptConsoleListener) listeners[i]).userRequest(userInput);
}
interpreter.exec(userInput);
String output = interpreter.getOutput();
if (interpreter.getState() == IScriptInterpreter.WAIT_NEW_COMMAND) {
prompt.setMode(true);
} else {
prompt.setMode(false);
}
for (int i = 0; i < listeners.length; i++) {
((IScriptConsoleListener) listeners[i]).interpreterResponse(output);
}
return output;
}
public void terminate() {
terminated = true;
try {
interpreter.close();
} catch (IOException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
public void dispose() {
partitioner.clearRanges();
colorBlack.dispose();
colorBlue.dispose();
colorRed.dispose();
terminate();
super.dispose();
}
}