在 zsh 中自动化 virtualenv activation/deactivation

Automating virtualenv activation/deactivation in zsh

我的代码如下所示:

has_venv_in_path() {
    unsetopt nomatch 2>/dev/null
    local path_to_search
    path_to_search=
    echo "searching in $path_to_search"
    if [[ ${path_to_search} = "/" ]]; then
        echo "no"
    fi

    ls ${path_to_search}/*/bin/activate > /dev/null 2> /dev/null
    if [ "$?" = '0' ]; then
        echo "yes"
    else
        has_venv_in_path $(dirname "$path_to_search")
    fi
}

has_venv_in_path 函数是我编写的,如果提供给它的路径不包含像 /home/user/foo 这样的波浪号,它就可以工作。如果提供 ~/foo 则进入无限递归。

所以我找到了扩展代字号的方法,但是我对bash的了解很少,所以我不能在我的函数中正确使用它。

有人可以帮忙吗?

假设我们有以下文件夹结构。

/code/foo/bar/baz
/code/foo/venv/bin/activate

鉴于这里的实际目标是在当前指定目录之上的某处寻找 virtualenv root...

find_venv_above() {
  local dir=${1:-$PWD}
  while [[ $dir = /*/* ]]; do
    [[ -e "$dir/bin/activate" ]] && {
      printf '%s\n' "$dir"
      return 0
    }
    dir=${dir%/*}
  done
  return 1
}

...用作:

if venv_root=$(find_venv_above); then
  echo "Currently in a virtualenv rooted at $venv_root"
fi

或者,如果你想在下面当前位置找到一个虚拟环境:

find_venv() {
  for option in "${1:-$PWD}"/*/bin/activate; do
    [[ -x "$option" ]] && {
      printf '%s\n' "${option%/bin/activate}"
      return 0
    }
  done
  return 1
}

用法类似。也就是说,如果您想递归多个级别而不是一个级别,我强烈建议您使用 find.