前情提要

今年六月份的时候我入手了一台M1芯片的Macbook pro,到手后配置环境的时候顺便按照网上的教程给terminal.app安装了oh-my-zsh!并配置好了agnoster主题和一些插件。虽然配置后的terminal.app的使用体验已经十分好了,但是在搭配使用conda时有一个小问题,即如下图所示,无法显示当前conda使用的虚拟环境。这样虽然也不是不能用,但是这让多年在Windows上使用conda的我很不习惯,而且不能看到当前所处于哪个环境下操作的时候总怕进错环境或者怎样,也非常不方便。

cannot show the conda_env

一开始本着也不是不能用的心态将就着使用了小半年,终于,今天我在使用conda的时候还是忍不了了。经过一番折腾终于把这个问题解决了,接下来我给大家分享一下折腾这个问题的一些经验。

初步修改

前期准备

由于一开始完全无从下手,网上文章基本上最多介绍到如何使用某个主题或者安装什么插件这种程度的配置,所以我对于怎样优化一个主题完全没有思路。在换了各种关键词进行检索,并且看了无数没有什么实际意义的文章后,终于找到了这篇文章,并且按照这篇文章上所介绍的步骤修改后成功满足了我70%的需求。

首先,按照文章所说,先要在~/.condarc文件的第一行前加上一行changeps1: false。如果之前没有修改过的话应该如下。

changeps1: false # 要添加的内容
# auto_activate_base: false

channels:
  - conda-forge
channel_priority: flexible

如果你不想每次启动终端的时候conda自动激活的话(比如使用其他Python版本之类的),可以再加入第二行的代码,就会禁止conda自动激活。这里我并没有这种需求但是以防万一就先写上然后注释掉了,如果你也不确定的话可以先和我一样,或者干脆不写也没关系,重点是第一行。。

修改主题文件

接下来进入正式修改agnoster主题文件的阶段了。主题文件的位置在~/.oh-my-zsh/themes/agnoster.zsh-theme,使用任意文本编辑软件打开即可。

theme file

进入文件后找到prompt_virtualenv()这个函数,如果你和我一样是第一次修改这个函数的话,此时的它应该是如下的样子。

# Display current virtual environment
prompt_virtualenv() {
  if [[ -n $VIRTUAL_ENV ]]; then
    color=cyan
    prompt_segment $color $PRIMARY_FG
    print -Pn " $(basename $VIRTUAL_ENV) "
  fi
}

这个函数的功能就是控制agnoster提示符显示虚拟环境的部分,所以我们修改它就行。修改的主要思路就是利用CONDA_PREFIX这个环境变量来获取当前激活的conda环境的所在的绝对路径,再通过basename CONDA_PREFIX来提取出环境的名字。

$ echo $CONDA_PREFIX
/Users/tyoukajyu/miniforge3

$ echo $(basename $CONDA_PREFIX)
miniforge3

文章按照以上的思路,最终将prompt_virtualenv()函数修改成以下样子。

prompt_virtualenv() {
  # Get the name of the virtual environment if one is active
  if [[ -n $VIRTUAL_ENV ]]; then
    local env_label=" $(basename $VIRTUAL_ENV) "
  fi

  # Get the name of the Anaconda environment if one is active
  if [[ -n $CONDA_PREFIX ]]; then
    if [[ -n $env_label ]]; then
      env_label+="+ $(basename $CONDA_PREFIX) "
    else
      local env_label=" $(basename $CONDA_PREFIX) "
    fi
  fi

  # Draw prompt segment if a virtual/conda environment is active
  if [[ -n $env_label ]]; then
    color=cyan
    prompt_segment $color $PRIMARY_FG
    print -Pn $env_label
  fi
}

修改完后保存、退出并重新启动terminal.app,激活conda后就可以看到效果了。

first version

这里是文章作者所展示的效果,如果没有问题的话应该也是和他一样的效果

进一步优化

但是这样并不是我最习惯的显示方式。首先是我希望conda环境的名字能够显示在最左端,即[env name] [xxx@macbook] ~ ,而非显示在本机名称后。另外,当conda的默认环境激活时,我希望显示的是base而非miniforge3,毕竟默认环境的名字就是base,这样更符合使用习惯。但是这两个问题上文所提到的那篇文章完全没有提及,所以接下来的内容只能靠自己来慢慢摸索了。

修改prompt显示顺序

这个问题相对比较好解决,还是在~/.oh-my-zsh/themes/agnoster.zsh-theme这个主题配置文件里,找到typeset -aHg AGNOSTER_PROMPT_SEGMENTS这个集合,这里面的顺序就代表了agnoster prompt的显示顺序。将集合内的prompt_virtualenv顺序提前即可。

typeset -aHg AGNOSTER_PROMPT_SEGMENTS=(
   prompt_status
   prompt_virtualenv # 将顺序提前到context前面
   prompt_context
#   prompt_virtualenv
   prompt_dir
   prompt_git
   prompt_end
)

这里根据个人习惯把prompt_virtualenv放在prompt_status的前面或者后面都可以,反正只要放在prompt_context前面就行。

修改默认环境名称

在正式下手修改之前,需要稍微熟悉一下zsh脚本的语法和配置文件所使用的代码风格(这里吐槽一下配置文件的代码风格过于古老,给我添了不少麻烦x)

首先是zsh脚本的判断语句。

# 一般情况下zsh的判断
if [[ 判断条件 ]] {
  # 条件为真时的代码
} elif [[ 另一个判断条件 ]] {
  # 条件为真时的代码
} else {
  # 条件为假时的代码
}

# 或者还有一种代码风格
if [[ 判断条件 ]]
  then
    # 条件为真时的代码
  elif [[ 另一个判断条件 ]]
  then
    # 条件为真时的代码
  else
    # 条件为假时的代码
fi
# 结束if语句
# 缩进并不必要

以上是两种正常人常用的代码风格,很好理解是吧。但是这个配置文件哪种风格都不属于!确切的讲应该是第二种风格的特殊的变体。

if [[ 判断条件 ]]; then
  # 条件为真时的代码
  elif [[ 另一个判断条件 ]]; then
    # 条件为真时的代码
  else
    # 条件为假时的代码
fi
# 结束if语句
# 缩进并不必要

另外需要注意一点的是,判断条件左右两个双中括号中间是要插入空格的。也就是说if [[判断条件]] 这样是错误的。另外我们在前文代码的判断语句里看到-n $str这样的条件,这里-n的意思是看后面的字符串$str,如果其长度为non-zero(即空字符串)则返回真,否则为假。除此之外还有一些关于zsh的变量、字符串操作等等语法,但是对于修改我们的配置文件来讲就不是非常必要了。

了解了上面的内容就可以基本看懂之前写的代码了,接下来可以考虑开始正式进一步优化。这里依旧是对之前的prompt_virtualenv()函数继续进行修改。修改思路十分简单粗暴,就是对当CONDA_PREFIX的值是/Users/[your Mac name]/miniforge3时,将env_label的变量值设为base即可。

prompt_virtualenv() {
  # Get the name of the virtual environment if one is active
  if [[ -n $VIRTUAL_ENV ]]; then
    local env_label=" $(basename $VIRTUAL_ENV) "
  fi

  # Get the name of the Anaconda environment if one is active
  if [[ -n $CONDA_PREFIX ]]; then
    if [[ -n $env_label ]]; then
      env_label+="+ $(basename $CONDA_PREFIX) "
    else
      if [[ $(basename $CONDA_PREFIX) == "miniforge3" ]]; then # 检测conda环境的名字是不是“miniforge3”
        local env_label=" base " # 如果是的话就将“env_label"修改为“base”
      else
        local env_label=" $(basename $CONDA_PREFIX) " # 如果不是的话就不用特别修改
      fi
    fi
  fi

  # Draw prompt segment if a virtual/conda environment is active
  if [[ -n $env_label ]]; then
    color=cyan
    prompt_segment $color $PRIMARY_FG
    print -Pn $env_label
  fi
}

注意12~16行是修改的内容。

修改后将配置文件保存并退出即可。再次启动终端后激活conda就可以看到100%符合我个人使用习惯的命令提示格式了。

finalimg

可喜可贺可喜可贺,终于把这个东西搞完可以去玩宝可梦明亮宝石了!

shinningpearl

参考文章

Last modification:November 22nd, 2021 at 10:24 pm
如果觉得我的文章对你有用,请随意赞赏