使用 tmux 或 screen 在 vi​​m 中切换模式时略有延迟

使用 tmux 或 screen 在 vi​​m 中切换模式时略有延迟

自从我使用 tmux 以来,在 Vim 中切换至插入模式和从插入模式切换不再是即时的。在Esc插入模式下按下 后,需要相当长的时间才能真正退出插入模式。按下Esc和随后的任何其他键后,切换是即时的,并且会执行按下的键的命令Esc。知道是什么原因造成的吗?

Vim 配置不是问题,因为当我在 tmux 之外运行 Vim 时不会发生延迟,所以这可能与 tmux 有关。顺便说一下,我使用 gnome-terminal。

另外值得注意的是,我似乎无法在 tmux 中定义键绑定Esc,我的计划是绑定Esc到:

bind Escape send-keys ^[

唉,似乎将任何东西绑定到Esctmux 都不起作用。屏幕上也出现了同样的问题。

答案1

仔细阅读手册页后发现,tmux 有一个选项。下面的命令~/.tmux.conf修复了延迟问题:

 set -sg escape-time 5

您必须重启 tmux 服务器或重新加载配置才能使此操作生效。为此,请source-file ~/.tmux.conf从 tmux 提示符发出。

正如@Jonathan Wheeler 所指出的(https://superuser.com/a/1809494),将逃逸时间设置为零并不是一个好主意,而是将其设置为一个足够低的值,这样您就不会受到延迟的困扰。

答案2

当我找到此页面时,我遇到了一个不同但类似的问题并试图解决,因此我将在此处发布该问题,以防它对正在寻找此答案并以相同方式找到此页面的其他人有所帮助。

问题:bash 中的 vi 模式从插入模式切换到命令模式时出现延迟

解决方案:在您的~/.inputrc文件中,添加set keyseq-timeout n某个n大于 0 的低值。 n默认值为 500ms,这就是导致延迟的原因。请参阅文档这里

另外,如果你想知道你处于哪种模式,请查看Dylan Cali 的 bash 分支

答案3

总结:

不要使用escape-time 0,而是将其设置为低的价值。

~/.tmux.conf

set -s escape-time 50  # ~5-100. https://superuser.com/a/1809494/224906

通过重新加载 tmux 配置或重新启动 tmux 服务器来完成。(在 CLI 中,运行 或tmux source-file ~/.tmux.conftmux kill-server; tmux

详细说明:

在过去的几个月里,我花了好几天的时间追踪远程连接到 tmux 服务器(通过 iTerm2 3.4.20 -> zsh 5.8.1 -> ssh 8.9p1 -> zsh 5.8.1 -> tmux 3.3a)时出现的一个非常烦人(非确定性且看似随机)的问题,我强烈建议不是将逃逸时间设置为 0(正如其他人所建议的那样,甚至tmux-敏感(这与我发帖时的这个问题有关),而是将逃逸时间设置为降低10 或 50 之类的值(默认值为 500)。

为什么?我最终在 GitHub 问题中找到了解决方案“tmux 3.3 将文本泄漏到 shell 中”

escape-time 0阻止 tmux 识别跨读取/数据包边界碎片化的转义序列。您应该将其提高到更合理的值,例如 100ms,这在大多数情况下应该足够了,同时仍然足够快,不会造成人机交互问题。

他使用的终端与我完全不同(wezterm 与 iTerm2),但却遇到了非常相似的问题,即 CSI(控制序列引入器)和 DCS(设备控制字符串)转义序列组合的问题 — 具体来说— 响应 CSI 转义序列(又名)和(又名)\033[>0;95;0c\033P>|iTerm2 3.4.20\033\\泄漏到 shell 中。(至少对我来说,它们似乎总是紧接着一个接一个地出现。)CSI > c\033 [ > cCSI > q\033 [ > q

过了一段时间后,这会导致在我的 vim 缓冲区中发生随机粘贴,然后Term2 3.4.20在粘贴的文本前面加上 [sic]。

进一步详细说明以帮助其他人寻找此解决方案:

组合的 CSI 和 DCS 序列\033[>0;95;0c\033P>|iTerm2 3.4.20\033\\在 vim 中导致以下情况:\033[>0;95;0c\033不执行太多操作,P粘贴 vim 的未命名/默认寄存器中的任何内容,>|将行制表符移到右侧,i进入插入模式,Term2 3.4.20插入缓冲区,\033退出插入模式,最后\\基本上不执行任何操作。

我观察到这种情况在我外出时更常发生,尤其是在使用不可靠且速度缓慢的移动连接时。这现在完全有道理,因为在这些条件下数据包延迟更大,而且我使用的是escape-time 0

TL;DR:不要使用escape-time 0;它的存在是有原因的。为其指定一个合理的低值(例如 5、50 或 100),这样在远程连接时仍能正常工作。根据需要进行调整以找到合适的平衡。如果值太高,它会干扰人机交互。如果值太低,您可能会遇到转义序列伪影和错误。

编辑:此问题和解决方案也被引用GitHub 上的此 Microsoft WSL 问题,这同样与这个问题相关。

编辑 #2:我还了解到,我上面描述的问题可能(也许更有可能)是由于TTY_QUERY_TIMEOUTtmux/tty.c未设置足够高escape-time 0,但这超出了这个问题的范围。出于上述原因,您不应该使用。

答案4

听起来你正在使用以 开头的映射ESC。当你按下 时ESC,vim 必须等待以查看下一个键是否是映射中的键。如果不是,它可以立即继续。

vim 配置可能依赖于终端,因此它不在 tmux 之外发生这一事实并不意味着什么。Vim 可以查询$TERM环境变量并根据其值选择不同的配置。

据我所知,gnome-terminal 使用xterm作为变量的值$TERM,而 tmux 使用screen,因此我将查看所有 vim 配置文件,以查找仅在变量$TERM等于 时使用的设置。我猜想系统上的某些 vim 配置文件设置了当终端为 时screen处理箭头键(以字符开头的键)的映射。 ESCscreen

你可以在启动 vim 之前临时更改$TERMtmux 中的变量来测试它。如果你的 shell 是 bash,请按如下方式调用 vim

TERM=xterm vim

在 tmux 中查看问题是否仍然存在。但是,您不应将其用作修复程序,因为 tmux 和 xterm 的终端功能可能存在差异,并且您可能会遇到一些问题。

相关内容