Vim 8.0 神秘:":au BufRead"处理程序中的":r!"命令会导致



我的.vimrc中有以下几行:

:function GitCommitMsg()
:  set tw=62
:  if getline(1) == ""
:    1 
:    r!git diff -w --minimal --cached
:    1d
:  endif
:  set syntax=diff
:endf 
:au BufRead,BufNewFile COMMIT_EDITMSG call GitCommitMsg()

多年来,上述内容在 Vim 7.x 上运行良好,但在 Ubuntu 18 上的 Vim 8 下开始行为不端。

if语句的内部是为新提交执行的。这个想法是在进行新提交时提供一些内容,但否则就不理会消息。

当该内部执行时,set tw=62set syntax=diff都不会生效。观测值分别为72gitcommit

不知何故,条件:r!调用导致了问题。如果我们将其注释掉:

:function GitCommitMsg()
:  set tw=62
:  if getline(1) == ""
:    1 
":    r!git diff -w --minimal --cached
:    1d
:  endif
:  set syntax=diff
:endf 
:au BufRead,BufNewFile COMMIT_EDITMSG call GitCommitMsg()

然后set tw=62set syntax=diff在所有情况下生效。

请注意,:r!git diff确实有效:git diff ...的输出加载到缓冲区中,前导空行由1d删除。

原因不是具体git diff或其产生的内容;无论我们使用:r!读取什么命令的输出,问题仍然存在。 因此,例如,这仍然存在问题:

:function GitCommitMsg()
:  set tw=62
:  if getline(1) == ""
:    1 
:    r!echo foo
:    1d
:  endif
:  set syntax=diff
:endf 
:au BufRead,BufNewFile COMMIT_EDITMSG call GitCommitMsg()

我们如何在au处理过程中将命令的输出读入缓冲区,而不会产生不必要的副作用,例如设置被破坏?

只需将BufRead,BufNewFile更改为BufWinEnter即可解决您的问题。

问题可能是由于在BufRead时只有缓冲区存在,但尚未选择(甚至尚未创建(的窗口。为了解决这个问题,Vim 利用了一些怪癖,所以你的脚本可能在某个临时窗口的上下文中运行(尝试跟踪win_getid()值(,之后 Vim 将从"上次使用的窗口"中复制窗口本地选项(例如tw(等等。

另一点是任意 Ex 命令必须具有窗口上下文才能运行(例如,有win_execute(),但没有buf_execute()(。因此,执行:read也可能导致操纵"临时"。

好吧,这可能是一种猜测而不是解释,但我希望你明白这个想法。

最新更新