2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.execution.console;
18 import com.intellij.execution.ExecutionManager;
19 import com.intellij.execution.Executor;
20 import com.intellij.execution.executors.DefaultRunExecutor;
21 import com.intellij.execution.filters.TextConsoleBuilderFactory;
22 import com.intellij.execution.ui.ConsoleView;
23 import com.intellij.execution.ui.ConsoleViewContentType;
24 import com.intellij.execution.ui.RunContentDescriptor;
25 import com.intellij.execution.ui.actions.CloseAction;
26 import com.intellij.ide.scratch.ScratchFileService;
27 import com.intellij.openapi.actionSystem.*;
28 import com.intellij.openapi.editor.Editor;
29 import com.intellij.openapi.editor.ex.util.EditorUtil;
30 import com.intellij.openapi.fileEditor.FileEditor;
31 import com.intellij.openapi.fileEditor.FileEditorManager;
32 import com.intellij.openapi.fileEditor.TextEditor;
33 import com.intellij.openapi.project.DumbAwareAction;
34 import com.intellij.openapi.project.Project;
35 import com.intellij.openapi.ui.popup.JBPopupFactory;
36 import com.intellij.openapi.util.Disposer;
37 import com.intellij.openapi.util.Key;
38 import com.intellij.openapi.util.TextRange;
39 import com.intellij.openapi.vfs.VirtualFile;
40 import com.intellij.psi.PsiFile;
41 import com.intellij.psi.PsiManager;
42 import com.intellij.util.NotNullFunction;
43 import com.intellij.util.PathUtil;
44 import com.intellij.util.containers.ContainerUtil;
45 import org.jetbrains.annotations.NotNull;
46 import org.jetbrains.annotations.Nullable;
48 import javax.script.ScriptEngine;
49 import javax.script.ScriptEngineFactory;
50 import javax.script.ScriptEngineManager;
53 import java.io.IOException;
54 import java.lang.ref.WeakReference;
55 import java.util.List;
61 public class RunIdeConsoleAction extends DumbAwareAction {
63 private static final String DEFAULT_FILE_NAME = "ide-scripting";
64 private static final Key<WeakReference<ConsoleView>> CONSOLE_VIEW_KEY = Key.create("CONSOLE_VIEW_KEY");
65 private static final Key<ConsoleHistoryController> HISTORY_CONTROLLER_KEY = Key.create("HISTORY_CONTROLLER_KEY");
67 private static final Map<String, ScriptEngineFactory> ourEngines = ContainerUtil.newLinkedHashMap();
70 for (ScriptEngineFactory factory : new ScriptEngineManager().getEngineFactories()) {
71 ourEngines.put(factory.getLanguageName(), factory);
76 public void update(AnActionEvent e) {
77 boolean enabled = !ourEngines.isEmpty() && e.getProject() != null;
78 e.getPresentation().setEnabledAndVisible(enabled);
82 public void actionPerformed(AnActionEvent e) {
83 if (ourEngines.size() == 1) {
84 runConsole(e, ourEngines.values().iterator().next());
87 DefaultActionGroup actions = new DefaultActionGroup(
88 ContainerUtil.map(ourEngines.values(), new NotNullFunction<ScriptEngineFactory, AnAction>() {
91 public AnAction fun(final ScriptEngineFactory engine) {
92 return new AnAction(engine.getLanguageName()) {
94 public void actionPerformed(@NotNull AnActionEvent e) {
95 runConsole(e, engine);
101 JBPopupFactory.getInstance().createActionGroupPopup("Script Engine", actions, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, false).
102 showInBestPositionFor(e.getDataContext());
106 protected void runConsole(@NotNull AnActionEvent e, @NotNull ScriptEngineFactory engine) {
107 Project project = e.getProject();
108 if (project == null) return;
109 List<String> extensions = engine.getExtensions();
111 String pathName = PathUtil.makeFileName(DEFAULT_FILE_NAME, ContainerUtil.getFirstItem(extensions));
112 VirtualFile virtualFile = IdeConsoleRootType.getInstance().findFile(project, pathName, ScratchFileService.Option.create_if_missing);
113 if (virtualFile != null) {
114 FileEditorManager.getInstance(project).openFile(virtualFile, true);
117 catch (IOException ignored) {
121 public static void configureConsole(@NotNull VirtualFile file, @NotNull FileEditorManager source) {
122 ScriptEngine engine = findScriptEngine(file);
123 if (engine == null) return;
124 //new ConsoleHistoryController(IdeConsoleRootType.getInstance(), engine.getFactory().getLanguageName())
125 MyRunAction runAction = new MyRunAction(engine);
126 for (FileEditor fileEditor : source.getEditors(file)) {
127 if (!(fileEditor instanceof TextEditor)) continue;
128 Editor editor = ((TextEditor)fileEditor).getEditor();
129 runAction.registerCustomShortcutSet(CommonShortcuts.CTRL_ENTER, editor.getComponent());
134 private static ScriptEngine findScriptEngine(@NotNull VirtualFile file) {
135 for (ScriptEngineFactory factory : ourEngines.values()) {
136 if (factory.getExtensions().contains(file.getExtension())) {
137 return factory.getScriptEngine();
143 private static void executeQuery(@NotNull Project project,
144 @NotNull VirtualFile file,
145 @NotNull Editor editor,
146 @NotNull ScriptEngine engine) {
147 TextRange selectedRange = EditorUtil.getSelectionInAnyMode(editor);
148 if (selectedRange.getLength() == 0) return;
149 String command = editor.getDocument().getText(selectedRange);
150 ConsoleView consoleView = getConsoleView(project, file, engine);
153 //myHistoryController.getModel().addToHistory(command);
154 consoleView.print("> " + command, ConsoleViewContentType.USER_INPUT);
155 consoleView.print("\n", ConsoleViewContentType.USER_INPUT);
156 Object o = engine.eval(command);
157 String string = o == null ? "nil" : String.valueOf(o);
158 consoleView.print(string, ConsoleViewContentType.NORMAL_OUTPUT);
159 consoleView.print("\n", ConsoleViewContentType.NORMAL_OUTPUT);
161 catch (Exception e) {
162 consoleView.print(e.getMessage(), ConsoleViewContentType.ERROR_OUTPUT);
163 //consoleView.print(ExceptionUtil.getThrowableText(e), ConsoleViewContentType.ERROR_OUTPUT);
164 consoleView.print("\n", ConsoleViewContentType.ERROR_OUTPUT);
169 private static ConsoleView getConsoleView(@NotNull Project project, @NotNull VirtualFile file, @NotNull ScriptEngine engine) {
170 PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
171 WeakReference<ConsoleView> ref = psiFile == null ? null : psiFile.getCopyableUserData(CONSOLE_VIEW_KEY);
172 ConsoleView existing = ref == null ? null : ref.get();
173 if (existing != null && !Disposer.isDisposed(existing)) return existing;
174 ConsoleView consoleView = TextConsoleBuilderFactory.getInstance().createBuilder(project).getConsole();
175 if (psiFile != null) psiFile.putCopyableUserData(CONSOLE_VIEW_KEY, new WeakReference<ConsoleView>(consoleView));
176 DefaultActionGroup toolbarActions = new DefaultActionGroup();
177 JComponent consoleComponent = new JPanel(new BorderLayout());
178 consoleComponent.add(consoleView.getComponent(), BorderLayout.CENTER);
179 consoleComponent.add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false).getComponent(),
181 final RunContentDescriptor descriptor = new RunContentDescriptor(consoleView, null, consoleComponent, file.getName()) {
183 public boolean isContentReuseProhibited() {
188 final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
189 //toolbarActions.add(new DumbAwareAction("Rerun", null, AllIcons.Actions.Rerun) {
191 // public void update(@NotNull AnActionEvent e) {
192 // ProgressIndicator indicator = indicatorRef.get();
193 // e.getPresentation().setEnabled(file.isValid() && (indicator == null || !indicator.isRunning()));
197 // public void actionPerformed(@NotNull AnActionEvent e) {
198 // consoleView.clear();
199 // rerunRunnable.run();
202 toolbarActions.add(new CloseAction(executor, descriptor, project));
203 for (AnAction action : consoleView.createConsoleActions()) {
204 toolbarActions.add(action);
206 ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
211 private static class MyRunAction extends DumbAwareAction{
212 private final ScriptEngine myEngine;
214 public MyRunAction(ScriptEngine engine) {
219 public void update(AnActionEvent e) {
220 Project project = e.getProject();
221 Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
222 VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
223 e.getPresentation().setEnabledAndVisible(project != null && editor != null && virtualFile != null);
227 public void actionPerformed(AnActionEvent e) {
228 Project project = e.getProject();
229 Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
230 VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
231 if (project == null || editor == null || virtualFile == null) return;
232 executeQuery(project, virtualFile, editor, myEngine);