Learning Vimscript The Hard Way — (12) Autocommands/自动命令

自动命令

现在我们来看一个几乎跟映射一样重要的主题:自动命令。

自动命令就是去告诉 Vim 当特定的事件发生的时候,运行指定的命令。让我们看一个例子:

:edit foo 打开一个文件然后用 :quit 马上把它关掉。看一下你的硬盘里面还没有那个文件存在。这是因为 Vim 在你第一次保存之前,并没有真的创建那个文件。

然后我们改一下它,让 Vim 在你编辑文件的时候就马上创建它。运行下面的命令。

:autocmd BufNewFile * :write

这里面有很多需要理解的,但试试它如何工作。再次运行 :edit foo,然后用 :quit 关掉它,然后看看你的硬盘。这次文件就会在那里了(当然,是空的)。

你要把 Vim 关掉才能删掉这个自动命令,我们往后就会谈及怎么去避免。

自动命令结构

让我们近距离看看我们刚才创建的自动命令:

:autocmd BufNewFile * :write
         ^          ^ ^
         |          | |
         |          | 要执行的命令
         |          |
         |          一个过滤事件的“模式(pattern)”
         |
         监视的“事件”

命令里面的第一部分是我们要监视的事件类型。Vim 提供了很多的时间供我们监视,其中包括:

  • 开始编辑一个尚不存在的文件。
  • 读取一个文件,不管他是否存在。
  • 切换缓冲区的 filetype 设置。
  • 一段时间没按键盘。
  • 进入插入模式。
  • 退出插入模式。

这只是可以用的事件的很小一部分,还有很多【事件】可以让你做很多有趣的事情。

命令里面的下一个部分是一个“模式”,让你在命令触发的时候更加明确。再开一个 Vim 然后运行下面的命令:

:autocmd BufNewFile *.txt :write

这个上一个命令几乎一样,但是这次它只会对名字以 .txt 结尾的那些【文件】起作用。

试一下运行 edit bar,然后 :quit,然后 :edit bar.txt,然后 :quit。你可以看到 Vim 自动写入了 bar.txt,但是没有写 bar 因为它没有匹配到这个模式。

这个命令最后的部分就是我们希望在事件触发的时候去运行的命令。这会很好的自解释【输入什么就执行什么】,除了一个:你不可以用诸如 <cr> 这样的特殊字符。我们在本书的后面会谈及如何突破这个限制,但现在你先知道有这么一回事就好了。

另一个例子

让我们在定义一个自动命令,这次用一个不同的事件。运行下面的命令:

:autocmd BufWritePre *.html :normal gg=G

这里面有点超纲了,因为 normal 我们会在后面才讲,但是现在你要忍耐一下,因为在这里很难找到一个贴切的例子。

创建一个文件叫做 foo.html。用 Vim 编辑它然后准确输入下面的文本,包括空格:

<html>
<body>
    <p>Hello!</p>
</body>
</html>

现在用 :w 保存这个文件,发生了什么呢?Vim 好像在它保存之前为我们调整了缩进!

现在我告诉你,运行 :normal gg=G 会告诉 Vim 去重新缩进当前的文件,先别管这是为什么。

我想让你关注的是这个自动命令,事件类型是 BufWritePre,它的意思是当你写入任意文件的时候会都会检查这个事件。

我们用了一个 *.html 的模式来确保这个命令只会对文件名以 .html 结尾的文件起作用。这就让我们可以针对特定的文件类型设置自动命令,这为我们后面的继续探索提供了一个有力的思路。

多事件

你可以在一个自动命令里面绑定多个事件,只需要在事件之间用逗号隔开就可以了。运行这个命令:

:autocmd BufWritePre,BufRead *.html :normal gg=G

这很像我们上一个命令,不同的是它在读取一个 HTML 文件的时候,也一样会重新调整缩进。这在对付有些协作者不好好缩进的情况特别有用。

有一个常用的 Vim 脚本惯用法:当你打开一个特定种类的文件,不管它是否存在,把 BufRead 和 BufNewFile 放一起执行命令。运行下面的命令:

:autocmd BufNewFile,BufRead *.html setlocal nowrap

这让你只要是在编辑 HTML 文件,就会关掉自动换行。

文件类型事件

有一个最重要的事件之一,就是 FileType 事件,这个事件会在 Vim 设置一个缓冲区的 filetype 的时候被触发。

让我们设置一些对不同文件有效的映射。运行下面的命令:

:autocmd FileType javascript nnoremap <buffer> <localleader>c I//<esc>
:autocmd FileType python     nnoremap <buffer> &ltlocalleader>c I#<esc>

打开一个 Javascript 文件(扩展名为 .js 的文件),找一行输入 <localleader>c。这会注释掉当前行。

现在打开一个 Python 文件(扩展名为.py)找一行输入 <localleader>c。这会注释掉当前行,不过这次会用 Python 的注释字符。

将我们上一章学到的缓冲区局部映射和自动命令一起用,我们可以为特定类型的文件创建映射。

这就可以减少我们在编码时候意识的负载。我们不需要去想移动去行首,然后添加一个注释字符,只需要简单的想“注释掉这行”。

练习

瞄一瞄 :help autocmd-events 看一下整个可以用来绑定自动命令的列表。现在你不需要一个一个记下来,感觉一下有什么事情是能做的就可以了。

创建一些 FileType 自动命令,里面用 setlocal 来对你感兴趣的文件类型设置一些选项。基于文件类型,你可能感兴趣的选项会有:wrap, list, spell, number

为你常常用的文件类型创建多一些“注释这一行”的自动命令。

把上面这些自动命令加到你的 ~/.vimrc 文件里面。当然,还是要用你之前设置的快捷映射来编辑和执行!


【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2014/10/vimscript-hard-12.html【Learning Vimscript The Hard Way — (12) Autocommands/自动命令】

发表评论

电子邮件地址不会被公开。 必填项已用*标注