我使用的是 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
并使用
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-window
和 split-window
并且该标志仅根据 their changelog 从 v3.0 引入。假设您可以使用前面提到的 -e
标志,步骤如下:
第 1 步(使用 tmux/tmux.conf):
在运行 tmux new-window
或 时,除了您可能已经使用的任何其他标志之外,还传递
。这会在新(子) Pane /窗口的环境中创建一个变量 -e "TMUX_PARENT_PANE_ID=#{pane_id}"
tmux 分割窗口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
命令以便:
- 在每个 Pane 的本地环境中拥有 anaconda 的
CONDA_DEFAULT_ENV
环境变量的副本。在下面的代码中,此副本将被命名为CONDA_DEFAULT_ENV_COPY
。如果再次获取 bashrc(或相应的等效文件),这对于在 Pane 中调用 conda 环境非常有用。 - 跟踪 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/