package org.rascalmpl.eclipse.repl; import java.lang.ref.WeakReference; import java.util.LinkedList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.ui.progress.UIJob; import org.rascalmpl.eclipse.Activator; import org.rascalmpl.eclipse.IRascalResources; public class RascalTerminalRegistry { private static final class Instance { public static final RascalTerminalRegistry manager = new RascalTerminalRegistry(); } public static RascalTerminalRegistry getInstance() { return Instance.manager; } private final List<WeakReference<RascalTerminalConnector>> connectors = new LinkedList<>(); private WeakReference<RascalTerminalConnector> focussed = null; private WeakReference<ILaunch> launch; public ILaunch getLaunch() { return launch != null ? launch.get() : null; } public void register(RascalTerminalConnector connector) { if (!connectors.stream().anyMatch(x -> x.get() == connector)) { connectors.add(new WeakReference<>(connector)); } } public void unregister(RascalTerminalConnector connector) { for (int i = 0; i < connectors.size(); i++) { if (connectors.get(i).get() == connector) { connectors.remove(i); break; } } } public RascalTerminalConnector findByProject(String project) { assert project != null; return connectors.stream().map(x -> x.get()).filter(x -> x != null && project.equals(x.getProject())).findFirst().orElse(null); } public void setActive(RascalTerminalConnector connector) { this.focussed = new WeakReference<>(connector); } public RascalTerminalConnector getActiveConnector(String project) { if (project != null) { RascalTerminalConnector f = focussed != null ? focussed.get() : null; if (f != null && connectors.stream().anyMatch(x -> x.get() == f) && f.getProject().equals(project)) { return f; } return findByProject(project); } else if (connectors.size() > 0) { return connectors.stream().map(x -> x.get()).filter(x -> x != null).findFirst().orElse(null); } else { return null; } } public void queueCommand(String project, String cmd) { RascalTerminalConnector connector = RascalTerminalRegistry.getInstance().getActiveConnector(project); if (connector != null) { connector.setFocus(); connector.queueCommand(cmd); } else { Activator.log("No terminal available for project " + project, new NullPointerException()); } } public void queueCommands(String project, Iterable<String> cmds) { RascalTerminalConnector connector = RascalTerminalRegistry.getInstance().getActiveConnector(project); if (connector != null) { connector.setFocus(); StringBuilder b = new StringBuilder(); for (String cmd : cmds) { b.append(cmd); b.append('\n'); } connector.queueCommand(b.toString()); } else { Activator.log("No terminal available for project " + project, new NullPointerException()); } } public static void launchTerminal(String project, String mode) { launchTerminal(project, null, mode); } public static void launchTerminal(String project, String module, String mode) { Job job = new UIJob("Launching console") { @Override public IStatus runInUIThread(IProgressMonitor monitor) { try { ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType type = launchManager.getLaunchConfigurationType(IRascalResources.LAUNCHTYPE); ILaunchConfigurationWorkingCopy launch = type.newInstance(null, "Rascal Project Terminal Launch [" + project + "]"); DebugUITools.setLaunchPerspective(type, mode, IDebugUIConstants.PERSPECTIVE_NONE); launch.setAttribute(IRascalResources.ATTR_RASCAL_PROJECT, project); launch.setAttribute(IRascalResources.ATTR_RASCAL_PROGRAM, module); getInstance().setLaunch(launch.launch(mode, monitor)); } catch (CoreException e) { Activator.getInstance().logException("could not start a terminal for " + project, e); } return Status.OK_STATUS; } }; job.setUser(true); job.schedule(); } private void setLaunch(ILaunch launch) { this.launch = new WeakReference<ILaunch>(launch); } }