Option to run python process in a terminal emulation mode (PY-22487)
[idea/community.git] / python / src / com / jetbrains / python / run / PythonRunConfiguration.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.jetbrains.python.run;
17
18 import com.intellij.execution.ExecutionException;
19 import com.intellij.execution.Executor;
20 import com.intellij.execution.configurations.*;
21 import com.intellij.execution.runners.ExecutionEnvironment;
22 import com.intellij.openapi.components.PathMacroManager;
23 import com.intellij.openapi.options.SettingsEditor;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.util.Comparing;
26 import com.intellij.openapi.util.InvalidDataException;
27 import com.intellij.openapi.util.JDOMExternalizerUtil;
28 import com.intellij.openapi.util.WriteExternalException;
29 import com.intellij.openapi.util.io.FileUtil;
30 import com.intellij.openapi.util.text.StringUtil;
31 import com.intellij.openapi.vfs.VirtualFile;
32 import com.intellij.psi.PsiElement;
33 import com.intellij.psi.PsiFile;
34 import com.intellij.refactoring.listeners.RefactoringElementAdapter;
35 import com.intellij.refactoring.listeners.RefactoringElementListener;
36 import com.jetbrains.python.PyBundle;
37 import org.jdom.Element;
38 import org.jetbrains.annotations.NotNull;
39
40 import java.io.File;
41
42 /**
43  * @author yole
44  */
45 public class PythonRunConfiguration extends AbstractPythonRunConfiguration
46   implements AbstractPythonRunConfigurationParams, PythonRunConfigurationParams, RefactoringListenerProvider {
47   public static final String SCRIPT_NAME = "SCRIPT_NAME";
48   public static final String PARAMETERS = "PARAMETERS";
49   public static final String MULTIPROCESS = "MULTIPROCESS";
50   public static final String SHOW_COMMAND_LINE = "SHOW_COMMAND_LINE";
51   public static final String EMULATE_TERMINAL = "EMULATE_TERMINAL";
52
53   private String myScriptName;
54   private String myScriptParameters;
55   private boolean myShowCommandLineAfterwards = false;
56   private boolean myEmulateTerminal = false;
57
58   protected PythonRunConfiguration(Project project, ConfigurationFactory configurationFactory) {
59     super(project, configurationFactory);
60     setUnbufferedEnv();
61   }
62
63   @Override
64   protected SettingsEditor<? extends RunConfiguration> createConfigurationEditor() {
65     return new PythonRunConfigurationEditor(this);
66   }
67
68   public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
69     return new PythonScriptCommandLineState(this, env);
70   }
71
72   public void checkConfiguration() throws RuntimeConfigurationException {
73     super.checkConfiguration();
74
75     if (StringUtil.isEmptyOrSpaces(myScriptName)) {
76       throw new RuntimeConfigurationException(PyBundle.message("runcfg.unittest.no_script_name"));
77     }
78   }
79
80   public String suggestedName() {
81     final String scriptName = getScriptName();
82     if (scriptName == null) return null;
83     String name = new File(scriptName).getName();
84     if (name.endsWith(".py")) {
85       return name.substring(0, name.length() - 3);
86     }
87     return name;
88   }
89
90   public String getScriptName() {
91     return myScriptName;
92   }
93
94   public void setScriptName(String scriptName) {
95     myScriptName = scriptName;
96   }
97
98   public String getScriptParameters() {
99     return myScriptParameters;
100   }
101
102   public void setScriptParameters(String scriptParameters) {
103     myScriptParameters = scriptParameters;
104   }
105
106   public boolean showCommandLineAfterwards() {
107     return myShowCommandLineAfterwards;
108   }
109
110   public void setShowCommandLineAfterwards(boolean showCommandLineAfterwards) {
111     myShowCommandLineAfterwards = showCommandLineAfterwards;
112   }
113
114   @Override
115   public boolean emulateTerminal() {
116     return myEmulateTerminal;
117   }
118
119   @Override
120   public void setEmulateTerminal(boolean emulateTerminal) {
121     myEmulateTerminal = emulateTerminal;
122   }
123
124   public void readExternal(Element element) {
125     super.readExternal(element);
126     myScriptName = JDOMExternalizerUtil.readField(element, SCRIPT_NAME);
127     myScriptParameters = JDOMExternalizerUtil.readField(element, PARAMETERS);
128     myShowCommandLineAfterwards = Boolean.parseBoolean(JDOMExternalizerUtil.readField(element, SHOW_COMMAND_LINE, "false"));
129     myEmulateTerminal = Boolean.parseBoolean(JDOMExternalizerUtil.readField(element, EMULATE_TERMINAL, "false"));
130   }
131
132   public void writeExternal(Element element) throws WriteExternalException {
133     super.writeExternal(element);
134     JDOMExternalizerUtil.writeField(element, SCRIPT_NAME, myScriptName);
135     JDOMExternalizerUtil.writeField(element, PARAMETERS, myScriptParameters);
136     JDOMExternalizerUtil.writeField(element, SHOW_COMMAND_LINE, Boolean.toString(myShowCommandLineAfterwards));
137     JDOMExternalizerUtil.writeField(element, EMULATE_TERMINAL, Boolean.toString(myEmulateTerminal));
138   }
139
140   public AbstractPythonRunConfigurationParams getBaseParams() {
141     return this;
142   }
143
144   public static void copyParams(PythonRunConfigurationParams source, PythonRunConfigurationParams target) {
145     AbstractPythonRunConfiguration.copyParams(source.getBaseParams(), target.getBaseParams());
146     target.setScriptName(source.getScriptName());
147     target.setScriptParameters(source.getScriptParameters());
148     target.setShowCommandLineAfterwards(source.showCommandLineAfterwards());
149     target.setEmulateTerminal(source.emulateTerminal());
150   }
151
152   @Override
153   public RefactoringElementListener getRefactoringElementListener(PsiElement element) {
154     if (element instanceof PsiFile) {
155       VirtualFile virtualFile = ((PsiFile)element).getVirtualFile();
156       if (virtualFile != null && Comparing.equal(new File(virtualFile.getPath()).getAbsolutePath(),
157                                                  new File(myScriptName).getAbsolutePath())) {
158         return new RefactoringElementAdapter() {
159           @Override
160           public void elementRenamedOrMoved(@NotNull PsiElement newElement) {
161             VirtualFile virtualFile = ((PsiFile)newElement).getVirtualFile();
162             if (virtualFile != null) {
163               updateScriptName(virtualFile.getPath());
164             }
165           }
166
167           @Override
168           public void undoElementMovedOrRenamed(@NotNull PsiElement newElement, @NotNull String oldQualifiedName) {
169             updateScriptName(oldQualifiedName);
170           }
171
172           private void updateScriptName(String path) {
173             myScriptName = FileUtil.toSystemDependentName(path);
174           }
175         };
176       }
177     }
178     return null;
179   }
180 }