1

Recently I updated my MacOS to Catalina. Now the default shell is zsh, i could like revert it to bash but I thought to play along. Now I came across a problem while wanting to customize my Command Prompt.

In $HOME/.zshenv I declared;

export ZDOTDIR="$XDG_CONFIG_HOME/zsh"

in that folder I have the .zshrc file. It contains the part of the conda initialization.

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/finn/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/Users/finn/anaconda3/etc/profile.d/conda.sh" ]; then
        . "/Users/finn/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="/Users/finn/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

But more importantly I source this prompt.sh file:

function promptcmd () {
    local blue="{33}";
    local cyan="{87}";
    local orange="{160}";
    local pink="{200}";
    local white="{15}";
    local yellow="{226}";

    # Set the terminal title and prompt.
    PROMPT=""; # working directory base name
    PROMPT+="%B"; # all bold

    PROMPT+="%F${pink}%n%f"; # username
    PROMPT+="%F${yellow}@%f"; # at
    PROMPT+="%F${orange}%M%f"; # hostname
    PROMPT+="%F${white} in %f"; # in
    PROMPT+="%F${blue}%~%f"; # directory
    PROMPT+="%F${white} \$ %f%b";

    if [[ $CONDA_DEFAULT_ENV != "base" ]]; then
        RPROMPT="%F${cyan}($CONDA_DEFAULT_ENV)%f";
    fi;
}

promptcmd

The PROMPT part works perfectly fine. But the part where I'd like to display my Anaconda Environment on the right hand side, it doesn't. The problem is that the Environment Variable $CONDA_DEFAULT_ENV is read incorrectly. If I were to just display the Variable in the prompt (without the if statement) I see how it always stays (base), even though I typed conda activate my_env, then entered echo $CONDA_DEFAULT_ENV and it returned my_env.

Is .zshrc not rereading the Environment Variables?

EDIT:

You are only calling promptcmd once; you want to define precmd instead (or all promptcmd from inside promptcmd) so that your prompt is redefined just before it is displayed every time.

chedner's commment helped; Just by renaming the promptcmd function, it at first somehow worked. The RPROMPT is empty until I conda activate my_env, then it says (my_env). But then some weird behavior followed, which I can only show you:

Example Terminal Output

Motonari
  • 63
  • 10
  • 1
    You are only calling `promptcmd` *once*; you want to define `precmd` instead (or all `promptcmd` from inside `promptcmd`) so that your prompt is redefined just before it is displayed *every* time. – chepner Sep 02 '20 at 20:48
  • @chepner : Holy, what? How was this only a naming thing? I used every thing exactly the same way and just renamed the function in `prompt.sh` to `precmd`, and it worked! Thank you very much! If you would like to explain the reasons any further, you or me could write an answer, which I could then accept as the correct answer. – Motonari Sep 03 '20 at 20:44
  • @chepner : Ok no, wait. So it stays `(base)` (without the `if`) until I enter `conda activate my_env` and then it becomes `(my_env)`. But after that change, it won't change back. No matter, if I just `conda deactivate` or `conda activate base`. – Motonari Sep 03 '20 at 20:51

2 Answers2

0

From the zsh man page:

... Commands are then read from $ZDOTDIR/.zshenv. .... Then, if the shell is interactive, commands are read from /etc/zshrc and then $ZDOTDIR/.zshrc.

If ZDOTDIR is not set, your $HOME is used instead. I don't know how conda activation works, but it is reasonable to assume, that it creates a new zsh child process. This child process now has ZDOTDIR defined, pointing to a different directory than your HOME, and your $HOME/.zshrc won't be sourced.

user1934428
  • 19,864
  • 7
  • 42
  • 87
  • I do define `$ZDOTDIR` in $HOME/.zshenv, as you can see in the first line. Is that not enough? – Motonari Sep 02 '20 at 11:58
  • and before that I define `export XDG_CONFIG_HOME=$HOME/.config` also in $HOME/.zshenv – Motonari Sep 02 '20 at 11:59
  • @Motonari : I wonder why you want to fiddle around with ZDOTDIR at all. The most common use is that you are running Zsh in an environment where your idea of what's your home directory differs from what is stored in `HOME`. In this case, I would set `ZDOTDIR` either before starting zsh, or maybe calculate it inside `/etc/zshenv`, depending on my application. I have never tried to change this variable, while zsh is already processing setup files inside your HOME. Why don't you run it with `-x` turned on to see, what files are actually executed? – user1934428 Sep 03 '20 at 09:23
  • It doesn't matter if I set `ZDOTDIR` and then in the `.zshrc` in the `ZDOTDIR` directory source another shell script at a third place or put it all into `$HOME/.zshrc`. The results remain the same. And I don't quite understand the `-x` option part, in which command should I use it? – Motonari Sep 03 '20 at 20:32
  • 1
    If you have the necessary permissions, I would put a `set -x` at the first command in `/etc/zshenv`, because this is where execution starts. Of course this will affect all users. If you don't want to do this, put it at the top of your `~/.zshenv`. – user1934428 Sep 04 '20 at 06:39
  • Interesting, so when I do so, it shows me every line executed! and now, I see how in the beginning it comes to the line `[[ $CONDA_DEFAULT_ENV != base ]]` which is shown as `[[ base != base ]]`. Consequently the code doesn't execute the following line. When I then `conda activate my_env`. The `if` expression is evaluated as `[[ my_env != base ]]` the following line sets `RPROMPT=%F{87}(my_env)%f`. If I `conda deactivate` after that, the `if` is evaluated as `[[ base != base ]]` again and the next line is not executed. So that's how I figured, that I simply had to `RPROMPT=""` every time! – Motonari Sep 04 '20 at 13:45
  • BTW, [here](https://stackoverflow.com/questions/63710783/pycharm-zsh-shell-does-not-have-full-user-path-variables-if-zdotdir-is-set-to-a/63710784?noredirect=1#comment112717311_63710784) is a somewhat related problem, which reveals that you likely can't set `ZDOTDIR` in one of the files in your `$HOME`. Perhaps zsh evaluates this variable when it starts up, and ignores when you fiddle with it later. – user1934428 Sep 06 '20 at 09:00
0

There were two parts missing before the EDIT.

I found out the first of these thanks to chepner's comment, which quotes:

You are only calling promptcmd once; you want to define precmd instead [...] so that your prompt is redefined just before it is displayed every time.

Apparently there is this naming convention, which causes my function promptcmd to only be executed once, when opening a new Terminal window. If you rename it to precmd it is executed for every prompt.

Then I had the issue displayed in the EDIT of the question. It worked every time a new conda env was activated, because $CONDA_DEFAULT_ENV, was different from base which caused the if clause to execute and set RPROMPT to "%F${cyan}($CONDA_DEFAULT_ENV)%f". Now it never vanished from the right side of my prompt when I entered conda deactivate and $CONDA_DEFAULT_ENV was back to base. After I learned a way to debug more easily thanks to user1934428's comment:

If you have the necessary permissions, I would put a set -x at the first command in /etc/zshenv, because this is where execution starts. Of course this will affect all users. If you don't want to do this, put it at the top of your ~/.zshenv.

Then, I quickly realized, that $RPROMPT was simply not reset before my custom prompt function precmd, which I naively asssumed. So what solved the last part, was a simple RPROMPT="" before the if, that sets RPROMPT when $CONDA_DEFAULT_ENV is not base.

Motonari
  • 63
  • 10