blob: f671b1a19fc6129f17a5a6be655685e7874c6720 [file] [log] [blame]
package org.jetbrains.plugins.terminal;
import com.google.common.base.Predicate;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.ui.UIUtil;
import com.jediterm.terminal.TtyConnector;
import com.jediterm.terminal.ui.TerminalSession;
import com.jediterm.terminal.ui.TerminalWidget;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.concurrent.ExecutionException;
/**
* @author traff
*/
public abstract class AbstractTerminalRunner<T extends Process> {
private static final Logger LOG = Logger.getInstance(AbstractTerminalRunner.class.getName());
@NotNull
protected final Project myProject;
public AbstractTerminalRunner(@NotNull Project project) {
myProject = project;
}
public void run() {
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, "Running the terminal", false) {
public void run(@NotNull final ProgressIndicator indicator) {
indicator.setText("Running the terminal...");
try {
doRun();
}
catch (final Exception e) {
LOG.warn("Error running terminal", e);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
Messages.showErrorDialog(AbstractTerminalRunner.this.getProject(), e.getMessage(), getTitle());
}
});
}
}
});
}
private void doRun() {
// Create Server process
try {
final T process = createProcess(null);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
initConsoleUI(process);
}
});
}
catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
protected abstract T createProcess(@Nullable String directory) throws ExecutionException;
protected abstract ProcessHandler createProcessHandler(T process);
@NotNull
public JBTabbedTerminalWidget createTerminalWidget(@NotNull Disposable parent) {
final JBTerminalSystemSettingsProvider provider = new JBTerminalSystemSettingsProvider();
JBTabbedTerminalWidget terminalWidget = new JBTabbedTerminalWidget(myProject, provider, new Predicate<Pair<TerminalWidget, String>>() {
@Override
public boolean apply(Pair<TerminalWidget, String> widget) {
openSessionInDirectory(widget.getFirst(), widget.getSecond());
return true;
}
}, parent);
openSessionInDirectory(terminalWidget, null);
return terminalWidget;
}
private void initConsoleUI(final T process) {
final Executor defaultExecutor = DefaultRunExecutor.getRunExecutorInstance();
final DefaultActionGroup toolbarActions = new DefaultActionGroup();
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false);
final JPanel panel = new JPanel(new BorderLayout());
panel.add(actionToolbar.getComponent(), BorderLayout.WEST);
actionToolbar.setTargetComponent(panel);
ProcessHandler processHandler = createProcessHandler(process);
final RunContentDescriptor contentDescriptor =
new RunContentDescriptor(null, processHandler, panel, getTerminalConnectionName(process));
contentDescriptor.setAutoFocusContent(true);
toolbarActions.add(createCloseAction(defaultExecutor, contentDescriptor));
final JBTerminalSystemSettingsProvider provider = new JBTerminalSystemSettingsProvider();
TerminalWidget widget = new JBTabbedTerminalWidget(myProject, provider, new Predicate<Pair<TerminalWidget, String>>() {
@Override
public boolean apply(Pair<TerminalWidget, String> widget) {
openSessionInDirectory(widget.getFirst(), widget.getSecond());
return true;
}
}, contentDescriptor);
createAndStartSession(widget, createTtyConnector(process));
panel.add(widget.getComponent(), BorderLayout.CENTER);
showConsole(defaultExecutor, contentDescriptor, widget.getComponent());
processHandler.startNotify();
}
public void openSession(@NotNull TerminalWidget terminal) {
openSessionInDirectory(terminal, null);
}
public static void createAndStartSession(@NotNull TerminalWidget terminal, @NotNull TtyConnector ttyConnector) {
TerminalSession session = terminal.createTerminalSession(ttyConnector);
session.start();
}
protected abstract String getTerminalConnectionName(T process);
protected abstract TtyConnector createTtyConnector(T process);
protected AnAction createCloseAction(final Executor defaultExecutor, final RunContentDescriptor myDescriptor) {
return new CloseAction(defaultExecutor, myDescriptor, myProject);
}
protected void showConsole(Executor defaultExecutor, @NotNull RunContentDescriptor myDescriptor, final Component toFocus) {
// Show in run toolwindow
ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor);
// Request focus
final ToolWindow window = ToolWindowManager.getInstance(myProject).getToolWindow(defaultExecutor.getId());
window.activate(new Runnable() {
public void run() {
IdeFocusManager.getInstance(myProject).requestFocus(toFocus, true);
}
});
}
@NotNull
protected Project getProject() {
return myProject;
}
public void openSessionInDirectory(@NotNull TerminalWidget terminalWidget, @Nullable String directory) {
// Create Server process
try {
final T process = createProcess(directory);
createAndStartSession(terminalWidget, createTtyConnector(process));
}
catch (Exception e) {
LOG.error("Can't open terminal session:" + e.getMessage(), e);
}
}
}