如何根据是否设置环境变量设置和使用 tmux.conf 中的变量

How to set and use variable in tmux.conf depending on whether an environment variable is set

(免责声明:我完全知道下面描述的问题的解决方案涉及编写和调用与 运行 tmux 服务器交互的 shell 脚本,或设置必要的环境启动 tmux 服务器之前的变量。我特地发布了这个问题,看看是否可以解决这个问题 而不 使用这样的脚本。)

问题总结

在我的 .tmux.conf 文件中,我试图根据是否在调用 tmux 之前设置了环境变量 FOO 来将局部变量 VALUE 设置为不同的值。然后我想在其他 tmux 命令中使用 VALUE 。不幸的是,我无法正确设置 VALUE 或在设置后访问它。

之前的尝试

根据我在联机帮助页和其他包含示例 tmux 代码的问答帖子中找到的内容,有多种方法可以实现上述内容。

尝试 1

我首先尝试使用 if-shell 命令。我尝试在有和没有 -b 标志的情况下使用此命令;两种情况的结果都是一样的。

我从示例中看到我可以使用语法 VALUE=bar 分配变量。鉴于此,这是我的配置的一个最小示例:

if-shell '[ -z "$FOO" ]' \
    'VALUE=bar' \
    'VALUE=baz'

set-environment -g RESULT $VALUE

终端会话:

$ echo $FOO

$ tmux
[detached (from session 0)]
$ tmux showenv -g VALUE
VALUE=bar
$ tmux showenv -g RESULT
RESULT=
$ killall tmux
$ export FOO=foo
$ echo $FOO
foo
$ tmux
[detached (from session 0)]
$ tmux showenv -g VALUE
VALUE=baz
$ tmux showenv -g RESULT
RESULT=

因此,虽然 VALUE 似乎已正确设置,但 RESULT 似乎无法访问 VALUE

尝试 2

联机帮助页还提到可以使用 %if 语句有条件地执行命令。使用这种格式,我尝试了以下配置:

%if #{#(if [ -z "$FOO" ]; then echo 1; else echo 0)}
VALUE=bar
%else
VALUE=baz
%endif

set-environment -g RESULT $VALUE

对于%if语句中的表达式,我尝试了几种变体,例如

即使有这些变化,无论是否设置了 FOO,我得到以下结果:

$ tmux
[detached (from session 0)]
$ tmux showenv -g VALUE
VALUE=baz
$ tmux showenv -g RESULT
RESULT=baz

因此,虽然 VALUE 可以访问,但它始终是 baz

遗憾的是,我找不到关于条件语句中使用的格式的有用示例。联机帮助页描述了如何访问 tmux 变量和一些格式提示;但是,关于访问环境变量,我所能找到的只是一种使用 shell 命令的方法:

In addition, the first line of a shell command's output may be inserted using #(). For example, #(uptime) will insert the system's uptime. When constructing formats, tmux does not wait for #() commands to finish; instead, the previous result from running the same command is used, or a placeholder if the command has not been run before.

我不确定这是否意味着我需要调用 #() 中的命令两次以避免使用占位符值,这可能是我的一个错误。

我也无法找到一种方法来轻松地打印 #{} 命令的结果来调试这部分语句。

问题总结

虽然我很感激任何可以帮助我解决这个问题的信息,但对我来说最紧迫的问题是:

tmux 运行配置配置的方式是将配置文件解析成一组命令,然后执行它们(有一个命令队列,所以配置文件被解析并追加到队列中然后从队列中执行)。所以有不同的解析和执行步骤。

您在尝试 1 中 运行 遇到的问题是 if-shell 在执行时是 运行,但 $VALUE 扩展发生在解析时。解析 set-environment 命令时未设置 VALUE。

在尝试 2 中,#() 未在 %if 内部处理,因此无法正常工作。但是,您可以直接在格式中使用该变量(如果已设置)。 %if 发生在解析时。

因此您需要确保分配和展开的顺序正确。你有几个选择。

您可以让 tmux 在命令执行时而不是解析时扩展变量。您可以通过将 setenv 包装在 运行-shell 中来做到这一点,例如:

   if-shell '[ -z "$FOO" ]' \
       'VALUE=bar' \
       'VALUE=baz'
   run 'tmux setenv -g RESULT $VALUE'

或者您可以像在尝试 2 中那样在解析时进行赋值,但您不能使用 #() - 您需要改用一种格式:

   %if #{==:#{FOO},}
   VALUE=bar
   %else
   VALUE=baz
   %endif
   setenv -g RESULT $VALUE

(请注意,配置文件中的 X=Y 等同于 setenv -g X=Y 除了它发生在解析而不是执行时 - 两者都设置全局环境。所以你可以摆脱 VALUE 并执行 RESULT =bar 或 setenv -g RESULT bar inside the %if.)

您也可以使用 display -p 打印格式。在 master 和 2.9 中你可以添加 -v 来查看它们是如何解析的:

$ tmux setenv -g FOO bar
$ tmux display -pv '#{==:#{FOO},baz}'
# expanding format: #{==:#{FOO},baz}
# found #{}: ==:#{FOO},baz
# modifier 0 is ==
#  expanding format: #{FOO}
#  found #{}: FOO
#  format 'FOO' found: bar
#  replaced 'FOO' with 'bar'
#  result is: bar
#  expanding format: baz
#  result is: baz
# compare == left is: bar
# compare == right is: baz
# replaced '==:#{FOO},baz' with '0'
# result is: 0
0