如何在.tmux.conf中编写if语句为不同的tmux版本设置不同的选项?

mrt*_*181 33 bash shell scripting if-statement tmux

我有一个.tmux.conf,我在安装了不同tmux版本的不同机器上使用.

我想根据tmux版本设置不同的鼠标选项.在一台机器上我有2.0另一个版本2.1.

我没有把他的意思弄清楚

if "[[(( $(tmux -V | cut -c 6-) < 2.1 ))]]" \
  "set -g mode-mouse on;" \
  "set -g mouse-resize-pane on;" \
  "set -g select-pane on;" \
  "set -g select-window on" "set -g mouse on"
Run Code Online (Sandbox Code Playgroud)

当我获取文件时

$ tmux source-file .tmux.conf

我收到这条消息

.tmux.conf:12: unknown command: set -g mouse-resize-pane on

我运行它的机器有版本2.1所以它不应该设置四个选项.

我想在运行tmux 2.0或更少时设置四个选项,或者在运行tmux 2.1时设置一个选项.

这个bash语句有效

$ tmux -V
tmux 2.1
$ if [[(( $(tmux -V | cut -c 6-) < 2.1 ))]];then echo $?;else echo $?;fi
1
Run Code Online (Sandbox Code Playgroud)

Tom*_*ale 41

根据@ ericx的回答@ thiagowfx的回答,我将以下内容放在一起,其中涵盖了2.0版以后列出的不兼容性:

# Version-specific commands [grumble, grumble]
# See: https://github.com/tmux/tmux/blob/master/CHANGES
run-shell 'tmux setenv -g TMUX_VERSION $(tmux -V | \
                            sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'

if-shell -b '[ "$(echo "$TMUX_VERSION < 2.1" | bc)" = 1 ]' " \
    set -g mouse-select-pane on; set -g mode-mouse on; \
    set -g mouse-resize-pane on; set -g mouse-select-window on; \
    set -g message-fg red; \
    set -g message-bg black; \
    set -g message-attr bright; \
    set -g window-status-bg default; \
    set -g window-status-fg default; \
    set -g window-status-current-attr bold; \
    set -g window-status-current-bg cyan; \
    set -g window-status-current-fg default; \
    set -g window-status-bell-fg red; \
    set -g window-status-bell-bg black; \
    set -g window-status-activity-fg white; \
    set -g window-status-activity-bg black"

# In version 2.1 "mouse" replaced the previous 4 mouse options
if-shell -b '[ "$(echo "$TMUX_VERSION >= 2.1" | bc)" = 1 ]' \
  "set -g mouse on"

# UTF8 is autodetected in 2.2 onwards, but errors if explicitly set
if-shell -b '[ "$(echo "$TMUX_VERSION < 2.2" | bc)" = 1 ]' \
  "set -g utf8 on; set -g status-utf8 on; set -g mouse-utf8 on"

# bind-key syntax changed in 2.4 -- selection / copy / paste
if-shell -b '[ "$(echo "$TMUX_VERSION < 2.4" | bc)" = 1 ]' " \
   bind-key -t vi-copy v   begin-selection; \
   bind-key -t vi-copy V   send -X select-line; \
   bind-key -t vi-copy C-v rectangle-toggle; \
   bind-key -t vi-copy y   copy-pipe 'xclip -selection clipboard -in'"

# Newer versions
if-shell -b '[ "$(echo "$TMUX_VERSION < 2.9" | bc)" = 1 ]' " \
   bind-key -T copy-mode-vi v   send -X begin-selection; \
   bind-key -T copy-mode-vi V   send -X select-line; \
   bind-key -T copy-mode-vi C-v send -X rectangle-toggle; \
   bind-key -T copy-mode-vi y   send -X copy-pipe-and-cancel 'xclip -selection clipboard -in'"

if-shell -b '[ "$(echo "$TMUX_VERSION >= 2.9" | bc)" = 1 ]' \
   "set -g message-style fg=red,bg=black; \
    set -g message-style bright; \
    set -g window-status-style          fg=default,bg=default; \
    set -g window-status-current-style  fg=default,bg=cyan,bold; \
    set -g window-status-bell-style     fg=red,bg=black; \
    set -g window-status-activity-style fg=white,bg=black"
Run Code Online (Sandbox Code Playgroud)

  • 需要注意的是,如果发布版本中存在字母和其他字符,这些版本检查将不起作用。本着 tmux 的 FU SEMVER 的精神,我在 GitHub 上提供了最后两个不符合这些版本检查的版本:“2.9a”和“3.0-rc3”。https://github.com/tmux/tmux/releases (3认同)
  • 谢谢汤姆,这很棒.我在我的repo github.com/sixarm/sixarm_tmux_dotfiles上添加了一封谢谢你 (2认同)
  • 作为在 OSX 和 2-3 个不同的 Linux 机器上使用相同点文件的人,我对您感激不尽!这个答案似乎是其中最通用的。 (2认同)
  • 感谢您的提醒@danemacmillan。他们的发布管理是FUBAR。我已经更新了一个“sed -n”。 (2认同)

小智 20

if-shell并不总是有效.相反,我使用shell脚本来加载正确版本的tmux.conf:

在.tmux.conf中:

run-shell "bash ~/.tmux/verify_tmux_version.sh"
Run Code Online (Sandbox Code Playgroud)

在verify_tmux_version.sh中:

#!/bin/bash

verify_tmux_version () {
    tmux_home=~/.tmux
    tmux_version="$(tmux -V | cut -c 6-)"

    if [[ $(echo "$tmux_version >= 2.1" | bc) -eq 1 ]] ; then
        tmux source-file "$tmux_home/tmux_2.1_up.conf"
        exit
    elif [[ $(echo "$tmux_version >= 1.9" | bc) -eq 1 ]] ; then
        tmux source-file "$tmux_home/tmux_1.9_to_2.1.conf"
        exit
    else
        tmux source-file "$tmux_home/tmux_1.9_down.conf"
        exit
    fi
}

verify_tmux_version
Run Code Online (Sandbox Code Playgroud)

有关详细信息:https: //gist.github.com/vincenthsu/6847a8f2a94e61735034e65d17ca0d66

  • 那个`bc` hack是硬核. (12认同)

Mic*_*ith 17

这是一种麻烦.在tmux中执行此操作的正确方法(不依赖于外部shell脚本)结合了Vincent和jdloft的响应功能.

if-shelltmux中的命令用作

if-shell [-bF] [-t target-pane] shell-command command [command]
               (alias: if)
    Execute the first command if shell-command returns success or the second command otherwise.  Before
    being executed, shell-command is expanded using the rules specified in the FORMATS section, including
    those relevant to target-pane.  With -b, shell-command is run in the background.

    If -F is given, shell-command is not executed but considered success if neither empty nor zero (after
         formats are expanded).
Run Code Online (Sandbox Code Playgroud)

请注意,tmux shell-command扩展将扩展表单的变量,#{pane_current_path}否则将单独保留命令.

更重要的是,请注意tmux 用于 /bin/sh -c执行我们指定的shell命令.因此,该命令必须符合POSIX,因此[[不保证表单的测试是可移植的.现代的Ubuntu和Debian系统,例如,符号链接/bin/shdash.

我们想运行一个POSIX兼容的shell命令来测试tmux版本,如果找到了所需的版本,则返回0(true).

if-shell '[ $(echo "$(tmux -V | cut -d" " -f2) >= 2.1" | bc) -eq 1 ]' \
    'command if true' \
    'command if false'
Run Code Online (Sandbox Code Playgroud)

例:

if-shell '[ $(echo "$(tmux -V | cut -d" " -f2) >= 2.1" | bc) -eq 1 ]' \
    'set -g mouse on; set -g mouse-utf8 on' \
    'set -g mode-mouse on; set -g mouse-resize-pane on; set -g mouse-select-pane on; set -g mouse-select-window on' 
Run Code Online (Sandbox Code Playgroud)

这正确地处理了我们正在进行浮点运算的事实,因此bc 是必需的.此外,不需要if/then/else/fi结构,因为[运算符本身会产生一个真值.

几个笔记

  • 继续到下一行的行不能有尾随注释,或者tmux会给出"未知命令"错误消息.
  • 可以省略"if if false".
  • 可以使用组合用于true或false的多个命令 ;
  • 该命令在底层shell上运行/bin/sh -c.其他使用[[或其他非POSIX语法的方法无法保证有效.

编辑:使用此答案的先前版本[[,但不适用于不使用bash的系统.替换[解决了这个问题.

  • 这是一个很好的答案。我实现了我所追求的目标,并且学到了一些关于 tmux 和 Bash 的知识。谢谢! (2认同)

Ing*_*kat 10

我还发现了不同tmux版本中的配置不匹配问题.在这里和SuperUser上的相关问题中查看了所有解决方案之后,我实现了以下变体:

# Version-specific configuration can be placed in ~/.tmux/${TMUX_VERSION}/*.conf
run-shell "for conf in ~/.tmux/$(tmux -V | cut -d' ' -f2)/*.conf; do tmux source-file \"\$conf\"; done"
Run Code Online (Sandbox Code Playgroud)

有了这个,特定于版本的配置可以放入特定版本的(多个)配置片段中.这类似于@VincentHsu的解决方案,但是:

  • 它不需要外部shell脚本.
  • 它不会分为固定版本范围(.../1.9到2.0/2.1 ......).相反,可以使用(sym)链接在多个tmux版本之间共享配置代码段.
  • 它不会对版本的单个文件名进行硬编码.通过为每个版本允许多个配置代码段,可以在版本之间共享部分,而其他部分则保持特定于版本.这应该提供最大的灵活性.
  • 原始中只有一个配置元素~/.tmux.conf.其他解决方案(如@TomHale中的解决方案)会复制每个配置元素的版本测试.


jdl*_*oft 7

Tmux if-shell可用于检查ZSH版本.

[[ `tmux -V | cut -d' ' -f2` -lt 2.1 ]]
Run Code Online (Sandbox Code Playgroud)

检查tmux版本是否大于或等于2.1.使用此功能,我们可以根据ZSH版本设置鼠标命令.

if-shell "[[ `tmux -V | cut -d' ' -f2` -lt 2.1 ]]" \
    'set -g mode-mouse on; set -g mouse-resize-pane on; set -g mouse-select-pane on; set -g mouse-select-window on'
Run Code Online (Sandbox Code Playgroud)

并将其设置为更高版本的tmux:

if-shell "[[ `tmux -V | cut -d' ' -f2` -ge 2.1 ]]" \
    'set -g mouse on; set -g mouse-utf8 on'
Run Code Online (Sandbox Code Playgroud)

  • 只要有人做布尔值,猫就会死掉?true:false`而不是`boolean` (12认同)
  • 这根本行不通.试试看``[[`tmux -V | cut -d'' - f2` -lt 2.1]]``在bash中.我得到`-bash:[[:2.2:语法错误:无效算术运算符(错误标记为".2")`.原因是这些测试操作符不处理浮点数,你需要`bc`. (3认同)
  • `sh` 和 `bash` 不允许对浮点数进行算术比较。请参阅[此答案](/sf/answers/2863161871/),了解使用台式计算器“bc”的解决方案 (2认同)

小智 7

在某些机器上,我使用双括号('[[')语法得到假阳性结果.所以我想出了一个使用awk的替代方案:

# Enable mouse for different versions of tmux
# (If 'awk' exits with status 0, 'if-shell' evaluates to true)
# tmux < v2.1:
if-shell "tmux -V | awk '{exit !($2 < \"2.1\")}'" \
    "setw -g mode-mouse on ; set -g mouse-select-pane on ; set -g mouse-resize-pane on ; set -g mouse-select-window on ;"
# tmux >= v2.1:
if-shell "tmux -V | awk '{exit !($2 >= \"2.1\")}'" \
    "set -g mouse on ;"
Run Code Online (Sandbox Code Playgroud)