在tmux中拆分窗格后,保持旧的conda env处于激活状态

时间:2019-10-21 08:00:49

标签: anaconda conda tmux

我使用的是tmux 2.6,正在使用一些不同的conda环境。拆分窗格/窗口后,我希望tmux也在子窗格中激活父窗格的环境。

我知道我可以添加要在split-window命令的按键绑定中执行的代码,并且当前活动的conda env的名称存储在$CONDA_DEFAULT_ENV中。但是,我尝试执行的所有命令均失败。

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

设置了窗格拆分命令。
bind \ split-window -h -c "#{pane_current_path}" '/some_path/bla.sh'

在我的tmux配置文件中,但是新创建的窗格在拆分后立即消失。

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

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

1 个答案:

答案 0 :(得分:2)

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

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

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

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

tmux new-window

其中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}传递,后续步骤将不起作用。

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

重新定义"#{pane_id}"命令,以便:

  1. 在每个窗格的本地环境中都有anaconda的conda环境变量的副本。在下面的代码中,此副本将命名为CONDA_DEFAULT_ENV。如果再次获取bashrc(或您对应的等效文件),这对于在窗格中调用conda环境很有用。
  2. 跟踪tmux会话的所有窗格的conda环境中的更改。为此,我们定义/更新了CONDA_DEFAULT_ENV_COPY tmux会话环境变量。与每个窗格的本地环境中定义的变量相反,会话中的所有窗格都可以访问tmux会话变量。

完成上述操作的代码为:

TMUX_SESSION_CONDA_ENVS

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

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

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

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