从零开始配置 vim(8)——文件类型检测

网友投稿 1427 2022-10-06

从零开始配置 vim(8)——文件类型检测

从零开始配置 vim(8)——文件类型检测

在上一章介绍自动命令的时候,我们提到可以使用 FileType来根据文件类型来触发事件,但是关于文件类型并没有深入的介绍,本篇我们来补充关于文件类型相关的内容,让大家更好的理解,看不懂也没关系,你只需要知道vim能识别各种编程语言的文件并启用事先定义好的配置即可。

跳过这篇文章对后面介绍的内容的理解不会有任何障碍,如果你不想看,直接拉到最后看结论即可本篇文章会针对​​neovim​​​ 的部分代码进行简单的剖析以便深入讲解文件类型。涉及到的​​neovim​​​ 版本为​​0.7.2​​,如果你使用的是更早版本,代码可能会不太一样,但是重点代码应该是一样的里面的代码可能有些小伙伴并不能理解,但是我们只是通过代码来描述它的一些流程,不理解代码能理解这个流程也是OK的,再退一步即使不理解流程,也没关系,毕竟我们只需要知道它有这个功能,不需要知道它的细节,不理解细节完全不会阻碍我们使用并对它进行配置

让我们进入相应的主题吧

文件类型简介

在 ​​vim​​​ 中可以使用 ​​filetype plugin indent on​​​ 来打开文件类型检测,而在 ​​neovim​​​ 中已经默认打开了这些属性,因此我们可以不设置这些。我们可以使用 ​​:filetype​​​ 来查看打开的状态。它会返回如下的内容 ​​filetype detection:ON plugin:ON indent:ON​​ 我们发现它包含了三个部分。

上述的设置语句我们可以将它拆分成3个部分:

filetype onfiletype plugin onfiletype indent on

它打开了三个东西,文件类型检测,针对文件类型相关的插件,针对文件类型相关的缩进和隐藏代码块的格式。下面我们依次来介绍这些东西

文件类型检测

​​filetype on​​​ 将打开文件类型检测。如果该项被打开,​​vim​​​ 在初始化的时候会读取脚本 ​​$VIMRUNTIME/filetype.vim​​​ 和 ​​$VIMRUNTIME/filetype.lua​​​ 的内容。这两个脚本用来识别文件类型。​​$VIMRUNTIME​​​ 是 ​​vim​​​ 里面的环境变量与 ​​$MYVIMRC​​​ 类似,我们可以通过使用 ​​:echo $VIMRUNTIME​​ 来查看具体的路径,也可以直接在命令模式中将它当做一个路径来使用

我们先来阅读以下 ​​filetype.vim​​ 的内容,在这段脚本中,我们可以发现大量这样的语句

au BufNewFile,BufRead *.cxx,*.c++,*.hh,*.hxx,*.hpp,*.ipp,*.moc,*.tcc,*.inl setf cppau BufNewFile,BufRead $VIMRUNTIME/doc/*.txt setf helpau BufNewFile,BufRead .htaccess,*/etc/ setf apacheau BufNewFile,BufRead */etc/apache2/sites-*/*.com setf apache

结合我们之前学习的自动命令相关的内容可以知道,这些代码会根据文件路径和后缀来自动设置文件类型。

从这写代码中可以看到,​​vim​​​ 也是靠命令来设置文件类型的。使用 ​​:setf​​​ 或者 使用 ​​:set filetype=c​​​ 或者使用它的简写形式 ​​set ft=c​​来设置文件类型

除了根据文件后缀,​​vim​​​ 也可以根据文件内容来判别文件类型。我们进入到 ​​filetype.lua​​​ 中可以看到,真正根据文件内容来决定类型是通过文件 ​​script.vim​​ 。该文件中主要使用正则表达式来匹配对应的特征值从而确定该文件类型,例如脚本中有这么一些代码

elseif s:line1 =~# '' set ft=xml" XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN")elseif s:line1 =~# '\' set ft=htmlelseif s:line1 =~? '-\*-.*C++.*-\*-' set ft=cpp

如果我们的文件无法满足 ​​vim​​​ 识别文件类型的要求,也可以在文件中添加注释来帮助 ​​vim​​​ 进行识别 例如使用如下注释来使​​​vim​​​ 确定它是一个 ​​c​​ 的代码

/* vim: ft=c */

可以在注释中使用 ​​vim: ft=​​​ 来设置文件类型。除了设置文件类型,这类注释还是设置像文件是否显示行号、列宽等等信息。更多信息可以查看 ​​:help modeline​​ 。

文件类型插件

在得到文件类型之后,​​vim​​​ 会根据文件类型加载不同的文件插件。它也是一个脚本,该脚本为 ​​$VIMRUMTIME/ftplugin.vim​​ 。打开这个文件,我们需要重点关注这么几句代码

for name in split(s, '\.') exe 'runtime! ftplugin/' . name . '.vim ftplugin/' . name . '_*.vim ftplugin/' . name . '/*.vim' " Load lua ftplugins exe printf('runtime! ftplugin/%s.lua ftplugin/%s_*.lua ftplugin/%s/*.lua', name, name, name)endfor

其中 ​​s​​​ 是一个字符串,它是一个包含了扩展名的文件名,在这里以 ​​.​​​ 作为分割,读取它以.分割的所有内容。例如 ​​aaa.bbb​​​ 会被分割为 ​​aaa​​​ 和 ​​bbb​​​。然后根据 ​​aaa​​​ 和 ​​bbb​​ 来分别执行下面的循环

​​exe​​​ 是用来执行对应文件内代码的语句。后面是一个字符串的拼接,假设当前打开的是一个​​.py​​​ 结尾的文件,对应的这句话就可以拼接为 ​​exe 'runtim! ftplugin/py.vim ftplugin/py__*.vim' ftplugin/py/*.vim​​​ 。后面两句拼接的内容相似,只是一个是给​​vim​​​ 脚本用的,一个是给​​ lua​​ 脚本用的。这里我们以 lua脚本为例。

​​runtime!​​​ 你可以理解成 ​​python​​​ 的 ​​import​​​ 或者 ​​c/c++​​​ 中的 ​​#include​​​,加载文件的路径一个是 ​​$VIMRUNTIME​​​ 所在路径,我们可以在 ​​$VIMRUNTIME/ftplugin​​​ 目录中找到很多语言预定义的设置,还有一个是配置文件所在的根目录。对于 ​​neovim​​​ 来说,这个路径就是 ​​~/.config/nvim​​ 。

这样我们就明白了,我们可以将对应文件类型的个性化配置放到 ​​~/.config/nvim/ftplugin​​​ 目录中。以 ​​python​​​ 为例来说的话。它会加载 ​​ftplugin/py.lua​​​ ,​​ftplugin/py_*.lua​​​ (以​​py​​​ 开头,以 ​​.lua​​​ 结尾的文件), ​​ftplugin/py/*.lua​​(py 目录下所有的lua文件)。

这样以后针对不同语言的设置完全可以在 ​​ftplugin​​ 中以对应名字命名。从而更好的组织我们的目录结构。

文件类型缩进

文件类型缩进运行我们为不同类型的文件设置不同格式的缩进,例如有的习惯使用4空格缩进,有的习惯使用 2空格或者8空格缩进。定义缩进格式的脚本是 ​​$VIMRUNTIME/indent.vim​​ 。在这个文件中我们又见到了类似的写法

for name in split(s, '\.') exe 'runtime! indent/' . name . '.vim' exe 'runtime! indent/' . name . '.lua'endfor

有了上面讲解的基础,理解这段代码就容易多了,它这里加载的主要是 ​​indent​​​ 目录中以后缀命名的缩进文件。但是它默认加载的文件比较少。从代码上看​​.py​​​ 文件如果使用 ​​python.vim​​​ 应该是不会被加载的,但是它默认的目录中针对 ​​python​​​ 的缩进仍然是以 ​​python.vim​​​ 命名,就证明它是可以被加载的。这里我还不理解为什么会被加载。有知道的小伙伴可以在评论区留言,大家一起交流学习。 好了,本章内容就到这里了。前面分析了那么多内容,总结起来就很简单的几点

最后的结论

​​vim​​​ 可以根据文件后缀和文件内容来决定文件类型。如果无法决定也可以使用 ​​set ft​​​ 来设置,或者在文件头部添加注释 ​​vim: ft=​​​ 来知名类型 我们可以针对不同文件类型进行个性化配置,包括插件和缩进,插件的用户配置文件的路径在 ​​​~/.config/nvim/ftplugin​​​ 中,以类型名命名。缩进的配置在 ​​~/.config/nvim/indent​​ 目录中,以类型名命名。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SQL图解面试题:如何分组比较?(窗口函数、group by)
下一篇:微信小程序支付及退款流程的介绍(微信小程序里付的款怎么退回)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~