package org.erlide.ui.editors.erl.actions;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.texteditor.ITextEditor;
import org.erlide.backend.BackendCore;
import org.erlide.backend.api.IBackend;
import org.erlide.backend.api.IBackendManager;
import org.erlide.engine.model.root.IErlProject;
import org.erlide.runtime.shell.BackendShellEvent;
import org.erlide.runtime.shell.BackendShellListener;
import org.erlide.runtime.shell.IBackendShell;
import org.erlide.ui.actions.SelectionDispatchAction;
import org.erlide.ui.console.ErlConsoleManager;
import org.erlide.ui.console.IErlangConsole;
import org.erlide.ui.console.IErlangConsolePage;
import org.erlide.ui.handlers.ErlangAbstractHandler;
import org.erlide.ui.internal.ErlideUIPlugin;
import org.erlide.util.ErlLogger;
public class SendToConsoleAction extends SelectionDispatchAction {
private final class ConsoleBackendShellListener implements BackendShellListener {
private final int offset;
private int counter;
private final IBackendShell shell;
public ConsoleBackendShellListener(final IBackendShell shell, final int offset) {
this.shell = shell;
this.offset = offset;
counter = 0;
}
@Override
public void changed(final BackendShellEvent event) {
if (shell == null) {
return;
}
counter++;
if (counter != 2) {
return;
}
final String[] messages = shell.getLastMessages(1);
if (messages.length == 0) {
return;
}
addMessage(offset, messages[0]);
}
}
private final ITextEditor editor;
private final boolean getOutput;
private ConsoleBackendShellListener consoleBackendShellListener;
IErlProject project;
@Override
public void run(final ITextSelection selection0) {
ITextSelection selection = selection0;
IErlangConsole console = null;
final IProject workspaceProject = project.getWorkspaceProject();
if (workspaceProject == null) {
return;
}
console = getConsole(workspaceProject);
if (console == null) {
final String message = "There is no runtime launched for this backend. Please start a runtime to send commands to.";
final Exception x = new Exception("No runtime started");
ErrorDialog.openError(getShell(), "No runtime", message, new Status(
IStatus.ERROR, ErlideUIPlugin.PLUGIN_ID, 0, x.getMessage(), x));
return;
}
console.getShell().removeListener(consoleBackendShellListener);
// if selection is empty, grab the whole line
selection = getLineSelection(selection, false);
// try to make the text a full erlang expression, ending with dot
String text = selection.getText().trim();
if (text.endsWith(",") || text.endsWith(";")) { //$NON-NLS-1$ //$NON-NLS-2$
text = text.substring(0, text.length() - 1);
}
if (!text.endsWith(".")) { //$NON-NLS-1$
text += "."; //$NON-NLS-1$
}
text += "\n"; //$NON-NLS-1$
// send it off to the console
if (getOutput) {
consoleBackendShellListener = new ConsoleBackendShellListener(
console.getShell(), getLineSelection(selection, true).getOffset());
console.getShell().addListener(consoleBackendShellListener);
}
final IErlangConsolePage consolePage = ErlideUIPlugin.getDefault()
.getErlConsoleManager().getPage(console);
consolePage.input(text);
super.run(selection);
}
private IErlangConsole getConsole(final @NonNull IProject aproject) {
final IBackendManager backendManager = BackendCore.getBackendManager();
final Set<IBackend> executionBackends = backendManager
.getExecutionBackends(aproject);
final ErlConsoleManager erlConsoleManager = ErlideUIPlugin.getDefault()
.getErlConsoleManager();
IErlangConsole result = null;
for (final IBackend backend : executionBackends) {
result = erlConsoleManager.getConsole(backend);
if (result != null) {
break;
}
}
return result;
}
public void addMessage(final int offset, final String message) {
final IDocument document = editor.getDocumentProvider()
.getDocument(editor.getEditorInput());
try {
final String delimiter = document
.getLineDelimiter(document.getLineOfOffset(offset - 1));
String nl = "";
if (delimiter == null) {
if (document instanceof IDocumentExtension4) {
final IDocumentExtension4 documentExtension4 = (IDocumentExtension4) document;
nl = documentExtension4.getDefaultLineDelimiter();
} else {
final String[] delimiters = document.getLegalLineDelimiters();
nl = delimiters[0];
}
}
final Display display = ErlideUIPlugin.getStandardDisplay();
final String addMessage = nl + message;
display.asyncExec(new Runnable() {
@Override
public void run() {
try {
document.replace(offset, 0, addMessage);
} catch (final BadLocationException e) {
}
}
});
ErlLogger.debug("message %s", message);
} catch (final BadLocationException e) {
}
}
protected ITextSelection getLineSelection(final ITextSelection selection0,
final boolean beginningOfNextLine) {
ITextSelection selection = selection0;
final IDocument document = editor.getDocumentProvider()
.getDocument(editor.getEditorInput());
if (selection.getLength() == 0) { // don't use isEmpty()!
selection = ErlangAbstractHandler.extendSelectionToWholeLines(document,
selection);
}
if (beginningOfNextLine) {
final int endLine = selection.getEndLine();
int offset;
try {
offset = document.getLineOffset(endLine)
+ document.getLineLength(endLine);
selection = new TextSelection(offset, 0);
} catch (final BadLocationException e) {
offset = document.getLength();
}
}
return selection;
}
public SendToConsoleAction(final IWorkbenchSite site, final ResourceBundle bundle,
final String prefix, final ITextEditor editor, final boolean getOutput,
final IErlProject project) {
super(site);
this.getOutput = getOutput;
this.project = project;
setText(getString(bundle, prefix + "label")); //$NON-NLS-1$
setToolTipText(getString(bundle, prefix + "tooltip")); //$NON-NLS-1$
setDescription(getString(bundle, prefix + "description")); //$NON-NLS-1$
this.editor = editor;
}
protected static String getString(final ResourceBundle bundle, final String key) {
try {
return bundle.getString(key);
} catch (final MissingResourceException x) {
}
return key;
}
}