Merge remote-tracking branch 'origin/master'
[idea/community.git] / python / python-terminal / src / com / jetbrains / python / sdk / PyVirtualEnvTerminalCustomizer.kt
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.sdk
17
18 import com.intellij.openapi.module.ModuleManager
19 import com.intellij.openapi.project.Project
20 import com.intellij.openapi.projectRoots.Sdk
21 import com.intellij.openapi.util.SystemInfo
22 import com.jetbrains.python.run.PyVirtualEnvReader
23 import com.jetbrains.python.run.findActivateScript
24 import org.jetbrains.plugins.terminal.LocalTerminalCustomizer
25 import java.io.File
26
27 /**
28  * @author traff
29  */
30
31 class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() {
32
33
34   override fun customizeCommandAndEnvironment(project: Project,
35                                               command: Array<out String>,
36                                               envs: MutableMap<String, String>): Array<out String> {
37     val sdk: Sdk? = findSdk(project)
38
39     if (sdk != null && PythonSdkType.isVirtualEnv(sdk)) {
40       // in case of virtualenv sdk on unix we activate virtualenv
41       val path = sdk.homePath
42
43       if (path != null) {
44
45         val shellPath = command[0]
46         val shellName = File(shellPath).name
47
48         if (shellName == "bash" || (SystemInfo.isMac && shellName == "sh") || (shellName == "zsh")) {
49           //for bash we pass activate script to jediterm shell integration (see jediterm-bash.in) to source it there
50           findActivateScript(path, shellPath)?.let { activate -> envs.put("JEDITERM_SOURCE", activate) }
51         }
52         else {
53           //for other shells we read envs from activate script by the default shell and pass them to the process
54           val reader = PyVirtualEnvReader(path)
55           reader.activate?.let {
56             envs.putAll(reader.readShellEnv().filterKeys { k -> k in arrayOf("PATH", "PS1", "VIRTUAL_ENV", "PYTHONHOME") })
57           }
58         }
59
60       }
61     }
62
63     // for some reason virtualenv isn't activated in the rcfile for the login shell, so we make it non-login
64     return command.filter { arg -> arg != "--login" && arg != "-l"}.toTypedArray()
65   }
66
67
68   private fun findSdk(project: Project): Sdk? {
69     for (m in ModuleManager.getInstance(project).modules) {
70       val sdk: Sdk? = PythonSdkType.findPythonSdk(m)
71       if (sdk != null && !PythonSdkType.isRemote(sdk)) {
72         return sdk
73       }
74     }
75
76     return null
77   }
78
79
80   override fun getDefaultFolder(): String? {
81     return null
82   }
83 }
84