romkatv / zsh4humans

A turnkey configuration for Zsh
MIT License
1.81k stars 116 forks source link

Integrated tmux breaks new VS Code venv activation #306

Open MicaelJarniac opened 6 months ago

MicaelJarniac commented 6 months ago

A few months ago, VS Code updated the way they activate virtual environments (at least for Python, I don't know about other languages).

The way it worked before was, after opening the terminal inside VS Code, it'd quickly "type" the venv activation command (something like source /foo/bar/baz/.venv/bin/activate), then run it, and also clear the screen I think.

This old method worked fine with Zsh for Humans and integrated tmux (after fixing #258 and #260).

Now, however, VS Code seems to no longer rely on automatically typing commands, and instead uses other methods, like injecting env vars, I think.

This new method breaks with Z4H and integrated tmux. Disabling tmux makes it work, though, at the expense of losing some Z4H features like the prompt at the bottom, which I really liked.

Here are some related issues and links:

I understand that this project has limited support and is provided as-is. I'm opening this issue mostly to inform others about this problem and a possible workaround.

And this may even be a problem with VS Code, not with this project.

romkatv commented 6 months ago

Thanks for opening this issue.

Do you know how exactly VSCode activates venv?

What do I need to do to activate venv myself through VSCode?

MicaelJarniac commented 6 months ago

Thanks for opening this issue.

Do you know how exactly VSCode activates venv?

What do I need to do to activate venv myself through VSCode?

To have VS Code activate venvs for you, at least in Python, I believe you need Python installed on your system, and the Python extension on VS Code. Here's their readme showing how to select an interpreter:

https://github.com/Microsoft/vscode-python?tab=readme-ov-file#set-up-your-environment

You open a .py file, and then on the bottom of the screen there'll be a button that allows you to choose which venv you want to use.

Pressing it should display a modal like this:

image

If you create a venv on the current folder, for example with python -m venv .venv, it should be available on the list for you to choose from.

Once a venv is selected, new terminals opened inside VS Code (with Ctrl+` for example) should have it activated automatically.

As for the exact mechanism that activates it, I'm not entirely sure, but I believe it's handled by the VS Code shell integration injecting and modifying env vars, like prepending the .venv/bin folder to PATH, and setting VIRTUAL_ENV to .venv.

I believe the issue with this new activation method is this, but I can't find the exact code changes:

Impressively fast response time by the way!

MicaelJarniac commented 6 months ago

This issue is a bit strange for me, though, as it seems to break things only partially. Like, sometimes the PATH will be modified, but the items in it will be in the wrong order.

With integrated tmux:

❯ which python
/home/micael/.pyenv/shims/python
❯ echo $PATH
/home/micael/.pyenv/shims:/home/micael/bin:/home/micael/.vscode/extensions/ms-python.python-2024.7.11341012/python_files/deactivate/zsh:/home/micael/projects/playground/.venv/bin:/home/micael/.pyenv/bin:/home/micael/.local/bin:/home/micael/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/micael/.cache/zsh4humans/v5/fzf/bin
❯ echo $VIRTUAL_ENV
/home/micael/projects/playground/.venv

Without integrated tmux:

❯ which python
/home/micael/projects/playground/.venv/bin/python
❯ echo $PATH
/home/micael/.vscode/extensions/ms-python.python-2024.7.11341012/python_files/deactivate/zsh:/home/micael/projects/playground/.venv/bin:/home/micael/.pyenv/shims:/home/micael/bin:/home/micael/.vscode/extensions/ms-python.python-2024.7.11341012/python_files/deactivate/zsh:/home/micael/projects/playground/.venv/bin:/home/micael/.pyenv/bin:/home/micael/.local/bin:/home/micael/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/micael/.cache/zsh4humans/v5/fzf/bin
❯ echo $VIRTUAL_ENV
/home/micael/projects/playground/.venv

And it seems to behave differently now, after a couple of days without using integrated tmux. Not sure why.

I'll also try investigating whether this could be due to how Pyenv is configured, as it appears to be prepending itself to PATH after VS Code prepends the venv.

MicaelJarniac commented 6 months ago

Here are my Zsh config files:

.zshrc ```zsh # Personal Zsh configuration file. It is strongly recommended to keep all # shell customization and configuration (including exported environment # variables such as PATH) in this file or in files sourced from it. # # Documentation: https://github.com/romkatv/zsh4humans/blob/v5/README.md. # Periodic auto-update on Zsh startup: 'ask' or 'no'. # You can manually run `z4h update` to update everything. zstyle ':z4h:' auto-update 'no' # Ask whether to auto-update this often; has no effect if auto-update is 'no'. zstyle ':z4h:' auto-update-days '28' # Keyboard type: 'mac' or 'pc'. zstyle ':z4h:bindkey' keyboard 'pc' # Start tmux if not already in tmux. # zstyle ':z4h:' start-tmux command tmux -u new -A -D -t z4h zstyle ':z4h:' start-tmux no # Whether to move prompt to the bottom when zsh starts and on Ctrl+L. zstyle ':z4h:' prompt-at-bottom 'yes' # Mark up shell's output with semantic information. zstyle ':z4h:' term-shell-integration 'yes' # Right-arrow key accepts one character ('partial-accept') from # command autosuggestions or the whole thing ('accept')? zstyle ':z4h:autosuggestions' forward-char 'accept' # Recursively traverse directories when TAB-completing files. zstyle ':z4h:fzf-complete' recurse-dirs 'no' # Enable direnv to automatically source .envrc files. zstyle ':z4h:direnv' enable 'yes' # Show "loading" and "unloading" notifications from direnv. zstyle ':z4h:direnv:success' notify 'yes' # Enable ('yes') or disable ('no') automatic teleportation of z4h over # SSH when connecting to these hosts. # zstyle ':z4h:ssh:example-hostname1' enable 'yes' # zstyle ':z4h:ssh:*.example-hostname2' enable 'no' # The default value if none of the overrides above match the hostname. zstyle ':z4h:ssh:*' enable 'no' # Send these files over to the remote host when connecting over SSH to the # enabled hosts. zstyle ':z4h:ssh:*' send-extra-files '~/.nanorc' '~/.env.zsh' # Clone additional Git repositories from GitHub. # # This doesn't do anything apart from cloning the repository and keeping it # up-to-date. Cloned files can be used after `z4h init`. This is just an # example. If you don't plan to use Oh My Zsh, delete this line. z4h install ohmyzsh/ohmyzsh || return # Install or update core components (fzf, zsh-autosuggestions, etc.) and # initialize Zsh. After this point console I/O is unavailable until Zsh # is fully initialized. Everything that requires user interaction or can # perform network I/O must be done above. Everything else is best done below. z4h init || return # Extend PATH. path=(~/bin $path) # Export environment variables. export GPG_TTY=$TTY # Source additional local files if they exist. z4h source ~/.env.zsh # Use additional Git repositories pulled in with `z4h install`. # # This is just an example that you should delete. It does nothing useful. z4h source ohmyzsh/ohmyzsh/lib/diagnostics.zsh # source an individual file z4h load ohmyzsh/ohmyzsh/plugins/emoji-clock # load a plugin # Define key bindings. z4h bindkey z4h-backward-kill-word Ctrl+Backspace Ctrl+H z4h bindkey z4h-backward-kill-zword Ctrl+Alt+Backspace z4h bindkey undo Ctrl+/ Shift+Tab # undo the last command line change z4h bindkey redo Alt+/ # redo the last undone command line change z4h bindkey z4h-cd-back Alt+Left # cd into the previous directory z4h bindkey z4h-cd-forward Alt+Right # cd into the next directory z4h bindkey z4h-cd-up Alt+Up # cd into the parent directory z4h bindkey z4h-cd-down Alt+Down # cd into a child directory # Autoload functions. autoload -Uz zmv # Define functions and completions. function md() { [[ $# == 1 ]] && mkdir -p -- "$1" && cd -- "$1" } compdef _directories md # Define named directories: ~w <=> Windows home directory on WSL. [[ -z $z4h_win_home ]] || hash -d w=$z4h_win_home # Define aliases. alias tree='tree -a -I .git' # Add flags to existing aliases. alias ls="${aliases[ls]:-ls} -A" # Set shell options: http://zsh.sourceforge.net/Doc/Release/Options.html. setopt glob_dots # no special treatment for file names with a leading dot setopt no_auto_menu # require an extra TAB press to open the completion menu z4h source ~/.my.zsh autoload -Uz compinit zstyle ':completion:*' menu select fpath+=~/.zfunc ```
.my.zsh ```zsh # Config # - In `.zshrc`: # - `zstyle ':z4h:' prompt-at-bottom 'yes'` # - Comment out tmux line # Pyenv export PYENV_ROOT="$HOME/.pyenv" command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" # pipx autoload -U bashcompinit bashcompinit eval "$(register-python-argcomplete pipx)" # Poetry fpath+=~/.zfunc autoload -Uz compinit && compinit # Editor export EDITOR="nvim" # Aliases alias la='ls -lAFh' # Config folder export XDG_CONFIG_HOME="$HOME/.config" # Functions function mkcd { dir="$*"; mkdir -p "$dir" && cd "$dir"; } # Smart completion zstyle ':completion:*' completer _complete zstyle ':completion:*' matcher-list '' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' '+l:|=* r:|=*' Smart completion # Firefox touch gestures export MOZ_ENABLE_WAYLAND=1 # VS Code Python activation temporary workaround # https://github.com/microsoft/vscode-python/issues/22899#issuecomment-1943661055 # [[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path zsh)" ```
romkatv commented 6 months ago

I cannot offer to debug the problem but if you figure out what VSCode does, and describe what exactly I need to click/type in VSCode to activate venv, there is a chance I'll do something.

MicaelJarniac commented 6 months ago

Seems like VIRTUAL_ENV does indeed break with integrated tmux:

❯ echo $PATH
/home/micael/.pyenv/shims:/home/micael/bin:/home/micael/.vscode/extensions/ms-python.python-2024.7.11341012/python_files/deactivate/zsh:/home/micael/projects/foo/bar/.venv/bin:/home/micael/.pyenv/bin:/home/micael/.local/bin:/home/micael/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/micael/.cache/zsh4humans/v5/fzf/bin
❯ echo $VIRTUAL_ENV
/home/micael/projects/playground/.venv

Here, I have project foo/bar active, but VIRTUAL_ENV still points to playground.

I cannot offer to debug the problem but if you figure out what VSCode does, and describe what exactly I need to click/type in VSCode to activate venv, there is a chance I'll do something.

Thanks a lot for this project and for taking the time to reply here. I'll investigate this further, and report back if I have anything worth sharing.

romkatv commented 6 months ago

Shot in the dark: try adding VIRTUAL_ENV to $Z4H/zsh4humans/.tmux.conf.