Vim 每次打开文件或常规语法时运行命令

Vim 每次打开文件或常规语法时运行命令,vim,Vim,我有一个突出显示尾随空格的语法规则: highlight Badspace ctermfg=red ctermbg=red match Badspace /\s\+$/ 这在我的.vimrc中。它工作得很好,但问题是我经常使用splits,而且匹配似乎只在您打开的第一个文件上运行,这也是应该的,因为.vimrc应该只运行一次 无论如何,我怎样才能使上述语法与任何打开的文件匹配?是否有“通用”语法文件?是否有其他方法可以在每次打开文件时运行match,而不是只打开一次?我想知道两者,因为我将来可

我有一个突出显示尾随空格的语法规则:

highlight Badspace ctermfg=red ctermbg=red
match Badspace /\s\+$/
这在我的
.vimrc
中。它工作得很好,但问题是我经常使用splits,而且
匹配
似乎只在您打开的第一个文件上运行,这也是应该的,因为
.vimrc
应该只运行一次


无论如何,我怎样才能使上述语法与任何打开的文件匹配?是否有“通用”语法文件?是否有其他方法可以在每次打开文件时运行
match
,而不是只打开一次?我想知道两者,因为我将来可能会使用其中一种。

您可以通过使用
autocmd来实现这一点:

highlight Badspace ctermfg=red ctermbg=red
autocmd BufEnter * match Badspace /\s\+$/
但是,还有另一种方法可以实现标记尾随空格的特定目标。Vim有一个用于突出显示“特殊”空格的内置功能,其中包括制表符(区别于空格)、尾随空格和非中断空格(字符160,看起来像普通空格,但不是)

请参见
:帮助列表
:帮助列表字符
。以下是我使用的:

set list listchars=tab:>·,trail:·,nbsp:·,extends:>
listchars
具有处理任何文件类型以及标记多个感兴趣的空白类型的优点。它的速度也快得多(在大型文件上匹配速度会明显慢),而且已经内置了

(请注意,这些是时髦的非ASCII点字符,如果您剪切并粘贴到支持UTF8的Vim中,应该可以使用这些字符。如果它们不适合您,您可以使用任何您喜欢的字符,例如句点或下划线)

以下是我的感受:


命令
:match
将突出显示应用于窗口,因此您可以使用
WinEnter
事件定义
:autocmd

:autocmd WinEnter * match Badspace /\s\+$/
请注意,已经有许多插件用于此目的,大多数基于此VimTip:

它们为您处理所有这些,并在插入模式下关闭高亮显示;有些还可以自动删除空白。事实上,我也为此编写了一套插件:。

这是使用
autocmd
实现的。您正在查找的事件是
bufwinter
VimEnter
。从Vim手册:

大腹便便 维门特 试着把这个放到你的vimrc中:

augroup BadWhitespace
    au!
    au VimEnter,BufWinEnter * match Badspace /\s\+$/
augroup END
augroup BadWhitespace
    au!
    au Syntax * syn match customBadWhitespace /\s\+$/ containedin=ALL | hi link customBadWhitespace Error
augroup END
执行
:帮助autocmd
了解更多信息

这是完全错误的,因为
:match
是窗口本地的,而不是缓冲区本地的。
的想法是正确的。不幸的是,没有什么好方法可以避免每次进入窗口时触发autocmd


更重要的是,这是一个自定义
语法的作业,而不是
匹配
解决此问题的正确方法实际上是使用
:syntax
来定义自定义
语法匹配

试着把这个放到你的vimrc中:

augroup BadWhitespace
    au!
    au VimEnter,BufWinEnter * match Badspace /\s\+$/
augroup END
augroup BadWhitespace
    au!
    au Syntax * syn match customBadWhitespace /\s\+$/ containedin=ALL | hi link customBadWhitespace Error
augroup END

编辑:还应注意,内置支持使用
'list'
选项突出显示尾随空格;请参见
:help'listchars'
:h hl SpecialKey
SpecialKey
是启用
'list'
时用于突出显示尾随空格字符的突出显示组)。

这很好,但我更喜欢只使用背景突出显示空间,而不使用其他内容。这将导致每次用户输入缓冲区时,而不仅仅是在加载缓冲区时,都会触发命令。事实上,问题在于
:match
是窗口本地的,而不是缓冲区本地的<应该使用code>WinEnter
。BufWinEnter
WinEnter
之间有什么区别?
BufWinEnter
在窗口中显示缓冲区时发生
WinEnter
在光标进入窗口时发生。这将导致用户每次进入窗口时都触发命令,这是不必要的;它应该只触发一次:当缓冲区加载时。实际上,我错了<代码>:match
是窗口本地,而不是缓冲区本地。它必须在WinEnter上完成。是的,我不担心重复进入同一窗口时会出现多余的调用;幸运的是,
:match
命令已经有了正确的“override previous”语义。这容易受到文件类型、
:syntax on/off
命令等更改的影响,甚至可能会影响原始语法高亮显示。在这方面,
:match
更合适。另请参阅我在回答中链接到的Vim Tips Wiki页面上的讨论。@QuinnStrahl是否有任何方法可以使此功能适用于未选择语法的文件(例如没有扩展名的文件?)。只要启用了
语法
,就不必有与文件关联的文件类型。如果需要,您可以简单地在Vim添加的每个缓冲区中定义这个“坏空白”语法。在我的答案中使用现在的代码,只需执行
:语法就可以了。我还用
“列表”
选项更新了答案,这可能与您的兴趣相关。