Vimscript编程指南

自动命令组

在前面的章节里,我们学习了自动命令。运行下面的命令: :autocmd BufWrite * :echom "Writing buffer!"

现在试着将缓存的内容写入文件,然后运行:messages来查看消息日志。你将会看到"Writing buffer!"的日志。

再次将缓存的内容写入文件,然后运行:message,你会看到“Writing buffer!”出现了两次。

现在继续运行相同的命令:

:autocmd BufWrite * :echom "Writing buffer!"

再次将当前缓存的内容写入文件,然后运行:message。你将会看

到“Writing buffer!”的日志出现了4遍。到底是什么原因导致的呢?

当你创建像上面那样的命令时(即是和之前命令一样的命令),vim无法区别你是要覆盖之前的命令,还是要新建一个命令,所以只好把它们当做两个不同的命令来执行。

问题

你现在知道了,在vim里是可以重复定义自动命令,你也许回想:“怎么搞?就这样么!"

真正的问题在于当你每次重新加载你的vimrc文件的时候,里面定义的自动命令也会重复加载,这样的话就会导致vim执行大量的重复命令,从而导致vim的运行速度很慢。

为了模拟上面的问题,运行下面的命令: :autocmd BufWrite * :sleep 200m

现在试着写入文件,或许这一点点延时你还感觉不到。现在运行下面的命令3次以上: :autocmd BufWrite * :sleep 200m :autocmd BufWrite * :sleep 200m :autocmd BufWrite * :sleep 200m

再次试着写入文件,现在的延时就很明显了吧。

不过很显然你不会在自动命令里不做其他的事,而只是休眠一会,但是一个vimrc文件很有可能超过一千行,并且很多都是自动命令。这些自动命令和你安装的插件里的自动命令加起来,肯定会降低你的vim的性能的。

自动命令组

不过对于上面的问题,vim提供了解决办法。第一步是把相似的自动命令放到同一个组里面。 打开一个新的vim实例,这样可以清空之前的自动命令,然后运行下面的命令: :augroup testgroup : autocmd BufWrite * :echom "Foo" : autocmd BufWrite * :echom "BAR" :augroup END

中间两行的空格没什么意义,只是用来排版的,如果你不喜欢的话也可以不输入。

把一个缓冲写入文件,在用:messages查看一下消息列表。你会看见“Foo”和“Bar”。现在再运行下面的命令: :augroup testgroup : autocmd BufWrite * :echom "Baz" :augroup END

现在猜猜如果你再次把缓冲的内容写入文件,将会有几条消息呢。你会猜是一条,把缓存里的内容写入然后运行:messges来看看你猜的是否正确。

清除自动命令组

当你写入文件的时候发生了什么呢?而你期望的又是什么呢?

如果你认为vim会自动用后面的自动命令组来替换前面的呢,那你就猜错了。不过别担心,大部分人第一次都这么认为。

当你多次用augroup来定义同一个自动命令组时,vim会把这些组的内容。

如果你想清除一个命令组,那么你可以在命令组的定义里用!autocmd来清除她。运行下面的命令: :augroup testgroup : !autocmd : autocmd BufWrite * :echom "Cats" :augroup END

在试着将缓存里的内容写入,这时vim只会输出“Cats”。

在vimrc文件里使用自动命令

现在我们知道了怎么来组合自动命令已经清除这些组合,我们可以用它来往我们的vimrc文件里添加自动命令,并且保证不会再每次载入vimrc文件的时候都添加重复的命令。

添加下面的内容到你的~/.vimrc文件里: augroup filetype_html autocmd! autocmd FileTpe html nnoremap <buffer> <localleader>f Vatzf augroup END

首先开始filetype_html,先清除它,然后定义命令,最后结束定义。如果我们再重新加载vimrc文件,这个清除的动作会防止Vim添加重复的命令。

练习

  • 检查一下你的vimrc文件,保证每一个自动命令都是在一个分组里。你可以把多个你命令放在同一个分组里,如果这个分组对你而言是有意义的话。
  • 试着找出最后一个映射的功能。
  • 阅读 :help autocmd-groups。