如何让 tmux 仅在 vim 不是 运行 时应用选项?

How to have tmux apply an option only when vim is not running?

我想在 tmux 配置文件中有一个选项,只有当 vim 不是当前 panel/window 中的 运行 时才会激活。特别是,该行如下:

bind-key -n MouseDown2Pane run "tmux set-buffer \"$(xclip -o -sel primary)\"; tmux paste-buffer"

这让我可以使用鼠标中键直接从主剪贴板粘贴到 tmux。它工作得很好,唯一的问题是它在 vim 内部有一个奇怪的行为(粘贴在错误的地方,奇怪的跳过行......)。如果我注释掉该行,则按中键单击粘贴到 vim 可以正常工作,但显然我失去了 tmux 中的粘贴功能。

所以,我的问题是:如果 vim 不是 运行,我如何让 tmux 应用该键绑定?

通过研究,我发现以下方法看起来很有前途,但我无法实现。

is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\S+\/)?g?(view|n?vim?x?)(diff)?$'"

if-shell "$is_vim" {command here}

编辑:另外,我也很乐意在 vim 中粘贴时让 "tmux set-buffer \"$(xclip -o -sel primary)\"; tmux paste-buffer" 命令正常工作。但是,出于某种原因,这看起来像是一项更困难的任务。

每次获取 .tmux.conf 文件时都会检查您的尝试,这(通常)仅在首次进行 tmux 会话时才会检查。

您每次 运行 命令时都需要检查它。幸运的是,这就像重新排列顺序一样简单。这是一个例子:

bind-key -n C-k if-shell 'test #{window_panes} -gt 1' 'select-pane -t :.-1' 'next-window'

在这里,Ctrl+k 检查我的 window 中是否有多个窗格。如果这样做,我将转到下一个窗格。如果我不这样做,我会去下一个 window.

我不是肯定的 $is_vim 可以是你绑定中的一个变量而不是完全写出来,你必须测试它,但它应该看起来像这样:

bind-key -n MouseDown2Pane if-shell "ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\S+\/)?g?(view|n?vim?x?)(diff)?$'" \
'<whatever it should do when vim is running' \
"tmux set-buffer \"$(xclip -o -sel primary)\"; tmux paste-buffer"

这看起来非常糟糕并且可能很慢,因为它必须 运行 那个 shell 命令来测试你每次使用那个按钮。

上面的想法是正确的,但是使用 pane_current_command 而不是 shell 命令会更快,例如:

if -F '#{m:*vim*,#{pane_current_command}}' ...

此外,我建议使用 "xclip...|tmux loadb -" 而不是 set-buffer,因为这样你就不会 运行 遇到剪贴板中 shell 特殊字符的问题。

对于问题的第一部分,您可以使用 #{?#{m:\*vim\*,#{pane_current_command}},0,1} 之类的东西来反转匹配,或者您可以使用 if-shell 的第二个参数而不是第一个参数,这样您就可以do if -F '...' '' 'mycommand' 其中第二个参数是空的。

if-shell 参数是 tmux 命令,但它们必须是一个参数。所以你需要把它们放在引号里——你会想要这样的东西:

bind -n MouseDown2Pane if -F '#{?#{m:\*vim\*,#{pane_current_command}},0,1}' 'run "xclip -o -sel primary | tmux load-buffer - ; tmux paste-buffer"'