jdx / mise

dev tools, env vars, task runner
https://mise.jdx.dev
MIT License
10.3k stars 295 forks source link

Python environments activating, but zsh prompt not updated #2027

Open max-santiago opened 6 months ago

max-santiago commented 6 months ago

Usually, when activating a Python virtual environment (whether manually or with virtual environment management tools such as direnv or autoenv), the VIRTUAL_ENV environment variable is set, and the PS1 variable will be overridden to display the virtual environment name in the shell.

image

I noticed that the auto-activation logic from jdx will correctly set VIRTUAL_ENV and point the python command to the correct executable, but it won't update the PS1 variable to show the environment name in the shell prompt, which is what I would expect to happen when activating an environment (whether manually or automatically with tools such as direnv or autoenv).

I think the relevant code snippet from the generic activate script is the following:

if ([ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]) && $(command -v cygpath &> /dev/null) ; then
    VIRTUAL_ENV=$(cygpath -u "$VIRTUAL_ENV")
fi
export VIRTUAL_ENV

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

if [ "x" != x ] ; then
    VIRTUAL_ENV_PROMPT=""
else
    VIRTUAL_ENV_PROMPT=$(basename "$VIRTUAL_ENV")
fi
export VIRTUAL_ENV_PROMPT

# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
    unset PYTHONHOME
fi

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
    _OLD_VIRTUAL_PS1="${PS1-}"
    PS1="(${VIRTUAL_ENV_PROMPT}) ${PS1-}"
    export PS1
fi

It would be nice to have mise update PS1 and restore it back to normal as it activates and deactivates Python environments whenever I switch directories on the shell.

jdx commented 6 months ago

I'm personally not a big fan of tools updating my PS1. I'd be open to this being optional functionality, but for me personally this is something I'd rather have configured in custom PS1 logic in my own rc file or with something like starship.

max-santiago commented 6 months ago

Got it! Thanks for the clarification. Ideally, I'd like the PS update logic to run on activation/deactivation of the environment rather than when starting up the shell or on changing directories. I actually had a custom rc file which did this in a single step, and I was able to, e.g. reference the VIRTUAL_ENV variable after it was set within my code when updating PS1.

It is unclear to me how/where I could add a "hook" that updates PS1 after mise activates/deactivates the environment. Apologies in advance if this is a bit basic. I'll look into starship in the meantime!

swirle13 commented 6 months ago

when I have pyenv and pyenv-virtualenv activate my environment, those are done with commands added to my zshrc or zprofile. The commands are

.zprofile:

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

.zshrc:

eval "$(pyenv virtualenv-init -)" 

Are there similar commands we could use to enable this behavior in our rc and profile files? This would allow users to opt into this functionality which would be provided as a first-party solution by mise while still following @jdx's opinion of not having mise itself directly update PS1 as a default behavior.

guyskk commented 4 months ago

the blog works for me: https://barker.codes/blog/adding-the-virtual-environment-name-to-your-prompt-with-oh-my-zsh/