.zshrc 文件中的环境变量读取不正确

Environment Variable is read incorrectly in .zshrc file

最近我将我的 MacOS 更新为 Catalina。现在默认的 shell 是 zsh,我想将它恢复为 bash,但我想一起玩。现在我在想要 自定义命令提示符 .

时遇到了问题

$HOME/.zshenv我声明了;

export ZDOTDIR="$XDG_CONFIG_HOME/zsh"

在该文件夹中我有 .zshrc 文件。它包含conda初始化的部分。

# >>> 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 <<<

但更重要的是我获取了这个 prompt.sh 文件:

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

PROMPT 部分工作得很好。但是我想在右侧显示我的 Anaconda Environment 的部分却没有。问题是环境变量$CONDA_DEFAULT_ENV读取不正确。如果我只是在提示中显示变量(没有 if 语句),我会看到它总是保持 (base),即使我输入 conda activate my_env,然后输入 echo $CONDA_DEFAULT_ENV它返回 my_env.

难道.zshrc没有重新读取环境变量吗?

编辑:

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 的评论很有帮助;只需重命名 promptcmd 函数,它起初就可以正常工作。在 conda activate my_env 之前 RPROMPT 是空的,然后它显示 (my_env)。但是随后出现了一些奇怪的行为,我只能告诉你:

来自 zsh 手册页:

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

如果未设置 ZDOTDIR,则使用您的 $HOME。我不知道 conda 激活是如何工作的,但可以合理地假设它创建了一个新的 zsh 子进程。此子进程现在已定义 ZDOTDIR,指向与您的 HOME 不同的目录,并且您的 $HOME/.zshrc 将不会被获取。

EDIT 之前 缺少两部分

由于 chepner 的评论,我发现了其中的第一个,其中引用了:

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.

显然有这个命名约定,这导致我的函数 promptcmd 在打开新终端 window 时只执行一次。如果将其重命名为 precmd,它会在 每个 提示时执行。

然后我在问题的编辑中显示了这个问题。每次激活新的 conda env 时它都会工作,因为 $CONDA_DEFAULT_ENV 不同于 base 导致执行 if 子句并将 RPROMPT 设置为 "%F${cyan}($CONDA_DEFAULT_ENV)%f".现在,当我输入 conda deactivate 并且 $CONDA_DEFAULT_ENV 返回到 base 时,它从未从提示符的右侧消失。由于 user1934428 的评论,我学会了一种更容易调试的方法:

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.

然后,我很快意识到,$RPROMPT 根本没有在我的自定义提示函数 precmd 之前重置,这是我天真地假设的。那么解决最后一部分的是 if 之前的简单 RPROMPT="",它在 $CONDA_DEFAULT_ENV 不是 base 时设置 RPROMPT。