Repository: python-poetry/poetry

Issue:
Update prompt environment variable when opening shell
<!--
  Hi there! Thank you for wanting to make Poetry better.

  Before you submit this; let's make sure of a few things.
  Please make sure the following boxes are ticked if they are correct.
  If not, please try and fulfill these first.
-->

<!-- Checked checkbox should look like this: [x] -->
- [x] I have searched the [issues](https://github.com/sdispater/poetry/issues) of this repo and believe that this is not a duplicate.
- [x] I have searched the [documentation](https://poetry.eustace.io/docs/) and believe that my question is not covered.

## Feature Request
<!-- Now feel free to write your idea for improvement. Thanks again 🙌 ❤️ -->
When running `poetry shell` you have no idea your in the virtualenv or not. Please add the virtualenv's name to the $PROMPT or $PS1 variable.


Discussion:
Please try the latest pre-release (Poetry version 1.0.0b8) that has this feature, in a working state.

I've tried the latest pre-release but it isn't working (on windows).
**Windows Cmd:**
```
C:\Users\...\pytestproject>poetry shell
Spawning shell within C:\Users\...\Appdata\Local\pypoetry\Cache\virtualenvs\pytestproject-vJd08mD1-py3.7
Microsoft Windows [Version 10.0.18363.476]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\...\pytestproject>
```

**Windows Powershell:**
```
PS C:\Users\...\pytestproject>poetry shell
Spawning shell within C:\Users\...\Appdata\Local\pypoetry\Cache\virtualenvs\pytestproject-vJd08mD1-py3.7
Microsoft Windows [Version 10.0.18363.476]
(c) 2019 Microsoft Corporation. All rights reserved.

PS C:\Users\...\pytestproject>
```

**Cmder**
```
C:\Users\...\pytestproject
λ poetry shell
Spawning shell within C:\Users\...\Appdata\Local\pypoetry\Cache\virtualenvs\pytestproject-vJd08mD1-py3.7
Microsoft Windows [Version 10.0.18363.476]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\...\pytestproject>
```

Also the cmder shell is not respected; e.g. it runs windows cmd.
> Please try the latest pre-release (Poetry version 1.0.0b8) that has this feature, in a working state.

Worked great for me on MacOS/bash shell.
It doesn't seem to work on Windows 1.0.0 to respect Powershell at all:

```
PS C:\work\ingress> poetry shell # EXECUTED FROM POWERSHELL
Spawning shell within C:\work\ingress\.venv
Microsoft Windows [Version 10.0.18362.476]
(c) 2019 Microsoft Corporation. All rights reserved.
Clink v0.4.9 [git:2fd2c2] Copyright (c) 2012-2016 Martin Ridgers
http://mridgers.github.io/clink


C:\work\ingress> # PROMPT IN CMD.EXE
```

using activate directly:

```
PS C:\work\ingress> .\.venv\Scripts\activate # EXECUTED FROM POWERSHELL
(.venv) PS C:\work\ingress> # PROMPT IN POWERSHELL
```
**This is for Cmder on Windows 10**

This is supposed to be an automatic feature on Cmder in the next release.
https://github.com/cmderdev/cmder/blob/master/vendor/clink.lua#L30-L36
But it has not still hit the scoop yet.
Other issue is that obviously what's mentioned by @rfkortekaas 
I attempted to go around by an alias poet
```λ alias poet=poetry shell $t %ConEmuDir%\..\init.bat```
This did & did not ~ work
```
C:\Prj\FinmartDelta  
λ alias poet=poetry shell $t %ConEmuDir%\..\init.bat
C:\Prj\FinmartDelta  
λ poet
Spawning shell within C:\Users\ny11559\AppData\Local\pypoetry\Cache\virtualenvs\finmartdelta-rJ3Qparu-py3.7
name=cmd        path=cmd.exe  {i attempted to put this directly in to shell.py, but failed}
Microsoft Windows [Version 10.0.18363.778]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Prj\FinmartDelta>                         {darn same thing}
C:\Prj\FinmartDelta>                         {hit return to see if I can activate it / not}
C:\Prj\FinmartDelta>poet                  {try again}
Virtual environment already activated: C:\Users\ny11559\AppData\Local\pypoetry\Cache\virtualenvs\finmartdelta-rJ3Qparu-py3.7

C:\Prj\FinmartDelta>                         {darn same thing}
C:\Prj\FinmartDelta                           {hit return again}
[finmartdelta-rJ3Qparu-py3.7] λ           {finally got what I needed}
C:\Prj\FinmartDelta  
[finmartdelta-rJ3Qparu-py3.7] λ 
```
Obviously, I need to do something here C:\Users\myUser\.poetry\lib\poetry\utils
```
 shell.py                                                                                                       buffers  
42         if cls._shell is not None:                                                                                   
43             return cls._shell                                                                                        
44                                                                                                                      
45         try:                                                                                                         
46             name, path = detect_shell(os.getpid())                                                                   
47         except (RuntimeError, ShellDetectionFailure):                                                                
48             raise RuntimeError("Unable to detect the current shell.")                                                
49                                                                                                                      
50         cls._shell = cls(name, path)                                                                                 
51                                                                                                                      
52         return cls._shell                                                                                            
53                                                                                                                      
54     def activate(self, env):  # type: (VirtualEnv) -> None                                                           
55         if WINDOWS:                                                                                                  
56             return env.execute(self.path)   
```
{tried adding pull path to init.bat but got another error.}

I suspect this doesn't work on Windows because the logic that calls "activate" in `poetry shell` is [bypassed on Windows](https://github.com/python-poetry/poetry/blob/258ba2992309544213cbf9c9410de9b35349d8c1/poetry/utils/shell.py#L62-L90), and has been since this feature was introduced in #1395.
I found a solution on Windows with AutoRun scripts.

You need to update registry and add a key "Autorun" REG_SZ below Computer\HKEY_CURRENT_USER\Software\Microsoft\Command Processor with the path to the script (in my case "C:\Users\ded\.rc.cmd".

Sample contents for this script:

```
@if "%RC_CMD%"=="1" goto :skip
@cls
@prompt [92m$p$g[0m 
@set RC_CMD=1
:skip
@if "%POETRY_ACTIVE%"=="1" prompt [95mpoetry [92m$p$g[0m 
```

Result:
![image](https://user-images.githubusercontent.com/626824/111375457-8dfc2980-869e-11eb-90ba-a35f53bb503c.png)

⚠️ in case of errors in this script, it will not be possible to launch a cmd anymore.
I assume that only works if you're using `cmd.exe` as your shell?
> I assume that only works if you're using `cmd.exe` as your shell?

There is a similar solution for PowerShell: https://superuser.com/a/886960/350929
I cannot tell for linux.
This already works on Linux, it's only Windows where it's bypassed for some reason: https://github.com/python-poetry/poetry/issues/1642#issuecomment-753911955
> I found a solution on Windows with AutoRun scripts.
>
> [...]

Improved version displaying name of project: https://gist.github.com/dedale/85b603ea378caa34a397818b47ad46d9
I adapted this [Pipenv solution](https://github.com/pypa/pipenv/issues/3505#issuecomment-582472194) to the Poetry Powershell.

Add the following line to $profile file (e.g. by running `notepad $profile` in Powershell).

```
function prompt{
  if ($env:POETRY_ACTIVE -eq 1) {
    $poetry_env = ($env:VIRTUAL_ENV -split "\\")[-1]
    $venv = ($poetry_env -split "-")[0..(($poetry_env -split "-").Length-3)] -join "-"
    "($venv) $(Get-Location)> ";
  } else {
    "$(Get-Location)$('>' * ($nestedPromptLevel + 1))";
  }
}
```

I can confirm that misconfiguring above addition did not break my Powershell.

Result:

![image](https://user-images.githubusercontent.com/3153681/142662067-112d09b7-1002-48c6-963a-8e3b7c5952a1.png)


Resolving patch:
diff --git a/src/poetry/utils/shell.py b/src/poetry/utils/shell.py
--- a/src/poetry/utils/shell.py
+++ b/src/poetry/utils/shell.py
@@ -1,5 +1,6 @@
 import os
 import signal
+import subprocess
 import sys
 
 from pathlib import Path
@@ -67,8 +68,19 @@ def get(cls) -> "Shell":
         return cls._shell
 
     def activate(self, env: "VirtualEnv") -> Optional[int]:
+        activate_script = self._get_activate_script()
+        bin_dir = "Scripts" if WINDOWS else "bin"
+        activate_path = env.path / bin_dir / activate_script
+
         if WINDOWS:
-            return env.execute(self.path)
+            if self._name in ("powershell", "pwsh"):
+                args = ["-NoExit", "-File", str(activate_path)]
+            else:
+                # /K will execute the bat file and
+                # keep the cmd process from terminating
+                args = ["/K", str(activate_path)]
+            completed_proc = subprocess.run([self.path, *args])
+            return completed_proc.returncode
 
         import shlex
 
@@ -81,9 +93,6 @@ def activate(self, env: "VirtualEnv") -> Optional[int]:
         if self._name == "zsh":
             c.setecho(False)
 
-        activate_script = self._get_activate_script()
-        bin_dir = "Scripts" if WINDOWS else "bin"
-        activate_path = env.path / bin_dir / activate_script
         c.sendline(f"{self._get_source_command()} {shlex.quote(str(activate_path))}")
 
         def resize(sig: Any, data: Any) -> None:
@@ -103,6 +112,10 @@ def _get_activate_script(self) -> str:
             suffix = ".fish"
         elif self._name in ("csh", "tcsh"):
             suffix = ".csh"
+        elif self._name in ("powershell", "pwsh"):
+            suffix = ".ps1"
+        elif self._name == "cmd":
+            suffix = ".bat"
         else:
             suffix = ""
 


Test patch: