【问题标题】:How to prevent <Esc> from waiting for more input in Insert Mode如何防止 <Esc> 在插入模式下等待更多输入
【发布时间】:2012-11-15 19:20:59
【问题描述】:

当我按 Esc 离开插入模式时,在 Vim 真正返回正常模式之前会有半秒的暂停。

通常这不会成为问题,因为在按下 Esc 后按下像 j 这样的普通模式命令会立即执行普通模式命令(没有上述等等),但我有映射inoremap &lt;Esc&gt; &lt;Esc&gt;:w&lt;CR&gt;,所以每次我离开插入模式时都会写入文件。我希望在我按下 Esc立即 进行写入,但是会有半秒的暂停。

我假设暂停是因为 Vim 正在等待更多输入,然后才决定我只是想键入一个简单的 Esc。这一定是因为某处的第一个字符是&lt;Esc&gt; 的映射,但我查看了我的.vimrc 并没有这样的映射。

此外,我什至运行了:map &lt;Esc&gt;,它返回了No such mapping。那么,如果没有这样的映射,为什么 Vim 似乎在等待更多输入,我该如何避免这种行为?


额外信息

这似乎是不可复制的,所以这里有一些更多的信息,以防有人真的想深入了解:

我正在使用Steve Francia's spf13 distribution of Vim,与my own .vimrc.local on top of it。我还使用 Vundle 安装了several additional plugins

注意: .vimrc.local 的最后来源是 .vimrc

【问题讨论】:

  • 我在我的 .vimrc 中尝试了这个映射,但没有发现明显的延迟......所以我无法重现这个问题。
  • @Magnus,谢谢,我猜这一定是由于我的特殊配置。有关更多信息,请参阅编辑。
  • 你确定暂停不是写文件的时间吗?
  • @Dan,相当肯定。停顿大约是正常写入文件时发生停顿时长的5-6倍。

标签: vim configuration keyboard-shortcuts


【解决方案1】:

更新(2014 年 3 月 19 日)

我找到了一个比尝试从文档的Tips & Tricks 部分查找以&lt;Esc&gt; 开头的所有映射更好的解决方案,由Powerline 提供。把它放在你的.vimrc

 " leave insert mode quickly
  if ! has('gui_running')
    set ttimeoutlen=10
    augroup FastEscape
      autocmd!
      au InsertEnter * set timeoutlen=0
      au InsertLeave * set timeoutlen=1000
    augroup END
  endif

请注意,这将导致在插入模式下无法使用以 &lt;Esc&gt; 开头的映射,但无论如何都不应该有任何映射,因为这解决了问题。


我在 spf13 的 .vimrc 中找到了导致问题的行:

" Fix home and end keybindings for screen, particularly on mac
" - for some reason this fixes the arrow keys too. huh.
map ^[F $
imap ^[F $
map ^[H g0
imap ^[H g0

我之前找不到它们的原因是因为它们不是使用&lt;Esc&gt; 映射的,而是使用^[ 映射的。很烦人!希望这可以帮助一些同样心怀不满的 spf13 用户:)

更新:

如果删除这些映射不起作用,那么它可能是来自插件的映射。

键入:verbose map &lt;Esc&gt; 以获取涉及Esc 的所有映射的列表。 verbose 部分指示 Vim 打印设置映射的位置。这应该有助于找出导致问题的原因。

另外,unmap &lt;Esc&gt; 命令可能很有用——它会删除 Esc 键的所有映射。

请注意,unmap 不会删除所有模式下的映射;输入:h unmap了解更多信息。

【讨论】:

  • 我正在使用 spf13 并且删除这些行不起作用。我试图在 vimrc.local 文件中取消映射。你是怎么解决的?我在 gnome 终端中使用 vim,如果这样映射 ESC 键,则修复 Alt 映射的解决方法不起作用。
  • 对于那些仍在寻求解决方案的人:set timeoutlen=0 " ESC 之后的等待时间(默认会导致烦人的延迟) from link
  • @navie,我相信这会导致 Vim 永远不会等待额外的输入,以防有不明确的映射,这对很多人来说可能是个问题。例如,如果你有jjj 的映射,Vim 不会等着看你是否输入了两次j,所以第二个映射将被有效地删除。请参阅我的更新答案以获得不同的修复。
  • 这种方法似乎只适用于 gui 版本。终端 vim 使用 . 退出插入模式仍然很慢
  • @btiernay,如果这对您来说仍然是个问题,请尝试更新后的解决方案——似乎在 gui 和终端 vim 中对我来说都可以可靠地工作。
【解决方案2】:

在我的例子中,是 tmux 注入了延迟(这对我来说完全是一个惊喜!)。

我通过将set -g escape-time 0 添加到我的tmux.conf 来修复它。


这可能对作者没有帮助,但是在使用许多不同的关键字组合搜索这个问题时首先出现这个问题,所以我希望它对某人有所帮助。


来源:here的第一条评论。

【讨论】:

    【解决方案3】:

    我不确定您描述的映射有什么问题,在我看来应该没问题。但是,我认为可以以更好的方式实现您想要完成的任务。您的映射基本上是在尝试创建 InsertLeave 事件,Vim 实际上已经内置了!

    尝试将这样的内容添加到您的.vimrc

    au InsertLeave * if &mod && expand('%')!=''|write|endif
    

    作为一个额外的好处,这个只有在它有一个文件名并且被实际修改过的情况下才会保存你的缓冲区。

    【讨论】:

    • 这太棒了!有没有办法在 InsertLeave 上做两件事?我想编写文件并调用!latexmk -pdf -f,这是一个 bash 命令,可将我正在处理的 TeX 文档编译为 pdf。
    • 您可以将 Vim 命令与| 连接,如答案所示,或定义额外的:autocmd。由于您可能希望自动保存所有缓冲区,但只为 TeX 编译,因此您可以使用 :autocmd InsertLeave &lt;buffer&gt; !latexmk ...,并将其放入 ~/.vim/ftplugin/tex_autocompile.vim
    • 如果你想做很多事情,另一个选择是让 autocmd 做call DoMyAutosaveStuff() 然后创建一个包含你想要它做的事情的名字的函数。当窗口失去焦点以及保存文件以及所有这些不同的事情时,我已经开始做很多事情了;让 autocmd 块成为“简单”函数调用并在其他地方拥有实际功能要容易得多。
    【解决方案4】:
    set timeoutlen=1000 ttimeoutlen=0
    

    timeoutlen - 映射延迟。

    ttimeoutlen - 键码延迟。

    Source

    【讨论】:

      猜你喜欢
      • 2022-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      相关资源
      最近更新 更多