anaconda - 在 tmux 中拆分 Pane 时保持旧的 conda env 处于激活状态

标签 anaconda conda tmux

我使用的是 tmux 2.6,并且正在使用一些不同的 conda 环境。在分割 Pane /窗口时,我希望 tmux 在子 Pane 中也激活父 Pane 的环境。

我知道我可以添加要在 split-window 命令的按键绑定(bind)中执行的代码,并且当前事件的 conda env 的名称存储在 $CONDA_DEFAULT_ENV 中。 。但是,我尝试的任何命令都失败了。

对于我的尝试,我有 conda activate $CONDA_DEFAULT_ENV/some_path/bla.sh并使用

设置 Pane 分割命令
bind \ split-window -h -c "#{pane_current_path}" '/some_path/bla.sh'

在我的 tmux 配置文件中,但新创建的 Pane 在分割后立即消失。

但是,即使没有,我想它也会重新激活基本环境,因为 $CONDA_DEFAULT_ENV env 变量随着新 shell 的启动而改变。

我想一个可行的解决方案必须首先存储旧的 $CONDA_DEFAULT_ENV 环境变量,将其转移到新的 tmux Pane ,然后使用它来设置 conda 环境,但我不知道如何实现这一点。

最佳答案

我已经使用 tmux 3.1b 完成了此任务。我发现您在发布问题时正在运行 tmux 2.6,但是,如果可以的话,请尝试更新到至少 v3.0,因为我的答案依赖于使用 -e 标志来new-windowsplit-window 并且该标志仅根据 their changelog 从 v3.0 引入。假设您可以使用前面提到的 -e 标志,步骤如下:

第 1 步(使用 tmux/tmux.conf):

在运行 tmux new-window 时,除了您可能已经使用的任何其他标志之外,还传递 -e "TMUX_PARENT_PANE_ID=#{pane_id}" tmux 分割窗口。这会在新(子) Pane /窗口的环境中创建一个变量 TMUX_PARENT_PANE_ID,该变量保存 tmux 分配给初始(父) Pane 的唯一 ID。

如果您使用键绑定(bind),那么您需要利用 tmux 的 run 以不太直观的方式(重新)编写它们。例如,为了将字母“c”绑定(bind)到 tmux new-window,tmux.conf 文件中的相应行必须如下所示:

bind c run 'tmux new-window YOUR_CURRENT_OPTIONS -e "TMUX_PARENT_PANE_ID=#{pane_id}"'

其中 YOUR_CURRENT_OPTIONS 表示在添加 -e 选项之前您可能已经存在的任何选项。如果您仅使用 bind c new-window YOUR_CURRENT_OPTIONS -e "TMUX_PARENT_PANE_ID=#{pane_id}",则 #{pane_id} 将作为文字 "# 传递{pane_id}”,接下来的步骤将不起作用。

Setp 2 [在您的 bashrc(或等效)文件中]:

重新定义 conda 命令以便:

  1. 在每个 Pane 的本地环境中拥有 anaconda 的 CONDA_DEFAULT_ENV 环境变量的副本。在下面的代码中,此副本将被命名为 CONDA_DEFAULT_ENV_COPY。如果再次获取 bashrc(或相应的等效文件),这对于在 Pane 中调用 conda 环境非常有用。
  2. 跟踪 tmux session 所有 Pane 的 conda 环境中的更改。我们通过定义/更新 TMUX_SESSION_CONDA_ENVS tmux session 环境变量来实现此目的。与每个 Pane 的本地环境中定义的变量相反,tmux session 变量可由 session 中的所有 Pane 访问。

完成上述内容的代码是:

# Redefine conda command, part a: Keep copy of original conda command/function
eval "original_$(declare -f conda)" 2> /dev/null
if [ $? -ne 0 ]; then
    original_conda () {
      command conda "$@"
    }
fi
# Redefine conda command, part b: Add new functionality related to items (i) and (ii).
conda () {
  # Run the regular conda
  original_conda "$@"
  local CONDA_RTN_CODE=$?

  # Keep a copy of CONDA_DEFAULT_ENV to restore the environment if, e.g.,
  # 'source ~/.bashrc' is run
  CONDA_DEFAULT_ENV_COPY=$CONDA_DEFAULT_ENV

  # Stop and return original_conda's return code if it fails
  [ $CONDA_RTN_CODE -ne 0 ] && return $CONDA_RTN_CODE

  # Do tmux-related stuff, but only if tmux is running and "$@" contains substring "activate"
  if [[ -n "$TMUX" ]] && [[ "$@" =~ .*"activate".* ]]; then
    # Create/update the *tmux* session env var "TMUX_SESSION_CONDA_ENVS"
    local TMUX_SESSION_CONDA_ENVS=$(tmux showenv TMUX_SESSION_CONDA_ENVS 2>/dev/null)
    if [[ $? -eq 0 ]]; then
      # Get list of conda envs for all panes except the current one
      local OLD_VALUES=$(echo $TMUX_SESSION_CONDA_ENVS | sed "s/TMUX_SESSION_CONDA_ENVS=//")
      local CONDA_ENV_OTHER_PANES=$(echo $OLD_VALUES | sed "s/$TMUX_PANE:\w*[[:space:]]*//g")
    fi
    # Include current pane's conda env info
    tmux setenv TMUX_SESSION_CONDA_ENVS "$TMUX_PANE:$CONDA_DEFAULT_ENV $CONDA_ENV_OTHER_PANES"
  fi
}

步骤 3 [也在您的 bashrc(或等效)文件中]:

在创建子级时查询父级 Pane conda 环境,最后激活子级中的 conda 环境。我当前使用的代码如下:

if [[ -n "$TMUX_PARENT_PANE_ID" ]]; then
    # Remember: "TMUX_SESSION_CONDA_ENVS", as per our redefined "conda" command, carries
    # info about changes in the the conda environments in all the session's panes.
    # TMUX_PARENT_PANE_ID makes it thus possible to query, from any child
    # pane, its parent's conda environment at the time the child was created.
    # This is exactly what will be done now.
    TMUX_SESSION_CONDA_ENVS=$(tmux showenv TMUX_SESSION_CONDA_ENVS 2>/dev/null)
    if [ $? -eq 0 ]; then
        PATT="(?<=${TMUX_PARENT_PANE_ID}:).*?(?=([[:space:]]|$))"
        PARENT_CONDA_ENV=$(echo $TMUX_SESSION_CONDA_ENVS | grep -oP "$PATT" | head -1)
        echo "Activate conda env '$PARENT_CONDA_ENV' of parent tmux pane '$TMUX_PARENT_PANE_ID'"
        conda activate $PARENT_CONDA_ENV
    fi
    # Clean up the pane's env (TMUX_SESSION_CONDA_ENVS remains in the tmux session env)
    unset TMUX_SESSION_CONDA_ENVS PATT PARENT_CONDA_ENV
    # Erase memory of parent tmux pane's ID so that the 'else' block below
    # is run if we re-source bashrc
    unset TMUX_PARENT_PANE_ID
else
    # Triger update of TMUX_SESSION_CONDA_ENVS and CONDA_DEFAULT_ENV_COPY
    # when the pane has no parent (very first pane or a pane where bashrc was
    # re-sourced after creation).
    [[ -n "$CONDA_DEFAULT_ENV_COPY" ]] && echo "Activate previous conda env '$CONDA_DEFAULT_ENV_COPY'"
    conda activate $CONDA_DEFAULT_ENV_COPY
fi

按照这些步骤操作后,只需关闭终端,再次打开它们并重新启动 tmux。我希望这会有所帮助。

关于anaconda - 在 tmux 中拆分 Pane 时保持旧的 conda env 处于激活状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58482113/

相关文章:

python - Anaconda Python 导致终端启动/提示缓慢

python - Octave 不在 Linux 上读取 anaconda python

python - Conda 中的语法错误

python - pip uninstall/conda删除后无法卸载tensorflow

linux - Home/End 键在 tmux 中不起作用

vim - tmux:如何在光标下打开文件

python - Anaconda - 通过 anaconda 提示更新包被限制

shell - 激活 conda 失败(采购 ~/.bashrc)

linux - .tmux.conf 不是在 Mac 上读取而是在 Linux 上读取?

python - 在 IPython 中安装 conda 包