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

时间:2019-04-24 21:28:59

标签: tmux

(免责声明:我完全知道,我下面描述的问题有解决方案,涉及编写和调用与正在运行的tmux服务器进行交互的shell脚本,或者在启动tmux服务器之前设置必要的环境变量。我特别是发布此问题,以查看是否有可能无需使用此类脚本来解决此问题。)

问题摘要

在我的.tmux.conf文件中,我试图根据调用tmux之前是否已设置环境变量VALUE来将局部变量FOO设置为不同的值。然后,我想在其他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语句中的表达式,我尝试了几种变体,例如

  • #{#([ -z "$FOO" ])}(我相信这不应该起作用,因为该命令不会产生任何输出,但是值得一试。)
  • #{==:#(if [-z "$FOO" ]; then echo 1; else echo 0),1}(以防万一明确的比较可行)

即使有这些变化,无论是否设置了FOO,我都会得到以下信息:

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

因此,尽管可以访问VALUE,但始终是baz

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

  

此外,可以使用#()插入shell命令输出的第一行。例如,#(uptime)将插入系统的正常运行时间。在构造格式时,tmux不会等待#()命令完成;相反,将使用先前运行同一命令的结果,如果先前未运行过该命令,则使用占位符。

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

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

问题摘要

尽管我希望获得任何可以帮助我解决该问题的信息,但对我而言最紧迫的问题是:

  • 为什么VALUE的设置正确,但是尝试1中的RESULT无法访问?
  • 如何在尝试2中编写我的条件,以确保正确设置VALUE

2 个答案:

答案 0 :(得分:2)

tmux运行配置的方式是将配置文件解析为一组命令,然后执行它们(存在命令队列,因此将配置文件解析并附加到队列中,然后从队列中执行) 。因此,有不同的解析和执行步骤。

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

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

因此,您需要确保分配和扩展按正确的顺序进行。您有两种选择。

您可以使tmux在命令执行时而不是解析时扩展变量。您可以通过将setenv包装在run-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或%if中的setenv -g结果栏。)

答案 1 :(得分:0)

还可以使用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