详谈Vim的配置层次结构与插件加载方式(一)

前言:vim依靠海量的插件库可以打造成一款神器的编辑器,但是网络上的教程都是几乎一模一样的,教我们怎么安装插件管理器,然后怎么安装插件,千篇一律,很少涉及到更本质的东西,本文会从几个重要的目录入手,把Vim的插件管理与加载详细的说明。

一、问题的引出

在使用Vundle或者是vim-plug插件管理工具的时候,当我们安装完之后,我们通过用户目录之下的.vimrc配置文件下载相应的插件,然后再用户目录之下的.vim文件夹之下就有了相应的插件所对应的文件夹,每一个文件夹下面或者是子文件夹之下都存在一个 xxxx.vim的文件,它是什么呢?

另一个问题就是,Vim仅从〜/ .vimrc文件中读取其所有设置和脚本吗?

先来回答两个问题:

(1)xxxx.vim 文件的本质就是脚本,因此在启动vim的时候会加载这些脚本文件,正式这些脚本的存在,才让我们可以自定义vim;

(2)〜/ .vimrc文件只是我们习惯性地用户配置方式,其实vim的配置还来自于很多其他的地方。

 

二、vim启动时到底加载了哪些脚本xxx.vim

前面说了,Vim的结构非常整洁,.vimrc只是多个配置文件中的其中一个而已。其实,你可以让Vim告诉你究竟加载了哪些脚本。试试看:启动终端,直接打开vim,或者是编辑计算机上的任意一个文件,如vim test.py。加载后,运行如下命令:

2.1 查看vim加载时加载了那些插件(执行了哪些脚本)

:scriptnames 

得到如下结果:

1: /etc/vimrc                                                                                                                                                                                                            
  2: /usr/share/vim/vim74/syntax/syntax.vim
  3: /usr/share/vim/vim74/syntax/synload.vim
  4: /usr/share/vim/vim74/syntax/syncolor.vim
  5: /usr/share/vim/vim74/filetype.vim
  6: /usr/share/vim/vim74/ftplugin.vim
  7: ~/.vimrc
  8: ~/.vim/autoload/plug.vim
  9: /usr/share/vim/vim74/ftoff.vim
 10: /usr/share/vim/vim74/indent.vim
 11: ~/.vim/plugged/nerdtree/plugin/NERD_tree.vim
 12: ~/.vim/plugged/nerdtree/autoload/nerdtree.vim
 13: ~/.vim/plugged/nerdtree/lib/nerdtree/path.vim
 14: ~/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim
 15: ~/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim
 16: ~/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim
 17: ~/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim
 18: ~/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim
 19: ~/.vim/plugged/nerdtree/lib/nerdtree/tree_dir_node.vim
 20: ~/.vim/plugged/nerdtree/lib/nerdtree/opener.vim
 21: ~/.vim/plugged/nerdtree/lib/nerdtree/creator.vim
 22: ~/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim
 23: ~/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim
 24: ~/.vim/plugged/nerdtree/lib/nerdtree/ui.vim
 25: ~/.vim/plugged/nerdtree/lib/nerdtree/event.vim
 26: ~/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim
 27: ~/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim
 28: ~/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim
 29: ~/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim
 30: ~/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim
 31: ~/.vim/plugged/python-mode/plugin/pymode.vim
 32: ~/.vim/plugged/python-mode/autoload/pymode.vim
 33: /usr/share/vim/vim74/plugin/getscriptPlugin.vim
 34: /usr/share/vim/vim74/plugin/gzip.vim
 35: /usr/share/vim/vim74/plugin/matchparen.vim
 36: /usr/share/vim/vim74/plugin/netrwPlugin.vim
 37: /usr/share/vim/vim74/plugin/rrhelper.vim
 38: /usr/share/vim/vim74/plugin/spellfile.vim
 39: /usr/share/vim/vim74/plugin/tarPlugin.vim
 40: /usr/share/vim/vim74/plugin/tohtml.vim
 41: /usr/share/vim/vim74/plugin/vimballPlugin.vim
 42: /usr/share/vim/vim74/plugin/zipPlugin.vim

清单比你预期的要长吗?我们发现加载了很多来自不同地方(即不同文件夹之下)的脚本xxx.vim文件(因为我这里安装了一些插件,有的可能没有这么多,这个数目是不一定的)。而且我们发现,不仅仅加载了我们自己安装的那些来自于.vim文件夹下面的插件,还有很多其他地方的插件,这是哪里来的呢?后面会说到。

这其实也就是vim在启动的时候会加载脚本,脚本越多就越耗时间。如果你安装了大量插件的话,那么编辑器需要做大量工作。你可以通过以下命令检查是什么导致编辑器的速度变慢,然后再看看它创建的start.log:

2.2 查看每一个插件的耗时

首先新建一个文件夹,然后在文件夹之下新建一个test.py文件,我的如下:

/home/zoe/Documents/python_test/test1.py

在该文件夹之下通过vim打开test1.py,使用下面的命令

vim --startuptime start.log test1.py(这里替换成自己需要打开的文件名)

这个时候就会打开我们的test1.py,与此同时,会在python_test文件夹之下出现了一个start.log的日志文件,打开查看如下:

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.011  000.011: --- VIM STARTING ---
000.146  000.135: Allocated generic buffers
000.224  000.078: locale set
000.229  000.005: window checked
000.612  000.383: inits 1
000.685  000.073: parsing arguments
000.686  000.001: expanding arguments
000.708  000.022: shell init
000.978  000.270: Termcap init
000.999  000.021: inits 2
001.067  000.068: init highlight
001.562  000.122  000.122: sourcing /usr/share/vim/vim74/syntax/syncolor.vim
001.654  000.268  000.146: sourcing /usr/share/vim/vim74/syntax/synload.vim
017.395  015.690  015.690: sourcing /usr/share/vim/vim74/filetype.vim
.
.
中间省略了
.
.
1157.594  000.048  000.048: sourcing /home/zoe/.vim/plugged/python-mode/autoload/pymode/tools/signs.vim
1157.772  000.060  000.060: sourcing /home/zoe/.vim/plugged/python-mode/autoload/pymode/tools/loclist.vim
1157.840  000.354  000.246: sourcing /home/zoe/.vim/plugged/python-mode/autoload/pymode/lint.vim
1158.458  1108.490: first screen update
1158.459  000.001: --- VIM STARTED ---

我们发现,打开这个test1.py文件,并加载这所有的插件花费了1158.458 ms(毫秒)

为了比较起见,下面我们看看如果没有这些配置,如果不加载这些插件要多少时间呢,Vim的启动速度有多快:

执行下面的命令打开test1.py

vim --clean --startuptime clean.log test1.py(这里替换成自己需要打开的文件名)

打开之后同样在python_test文件夹之下会出现一个clean.log的日志文件,里面内容如下:

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.000  000.000: --- VIM STARTING ---
000.000  000.000: Allocated generic buffers
001.000  001.000: locale set
001.000  000.000: clipboard setup
001.000  000.000: window checked
003.000  002.000: inits 1
006.000  003.000: parsing arguments
007.000  001.000: expanding arguments
052.000  045.000: shell init
052.000  000.000: Termcap init
052.000  000.000: inits 2
052.000  000.000: init highlight
067.000  001.000  001.000: sourcing D:\Program Files (x86)\Vim\vim81\syntax\syncolor.vim
067.000  002.000  001.000: sourcing D:\Program Files (x86)\Vim\vim81\syntax\synload.vim
073.000  005.000  005.000: sourcing D:\Program Files (x86)\Vim\vim81\filetype.vim
.
.
.
.
256.000  000.000: BufEnter autocommands
256.000  000.000: editing files in windows
256.000  000.000: VimEnter autocommands
256.000  000.000: before starting main loop
263.000  007.000: first screen update
263.000  000.000: --- VIM STARTED ---

我们发现,加载的内容少了很多,时间少了很多,总共只花费了263毫秒

注意:

(1)--clean这个参数的含义如下:

  --clean              'nocompatible', Vim defaults, no plugins, no viminfo,

即仅仅使用默认的vim设置,不加载插件,也不启用其它的vimrc的配置等。

(2)另外,vim8.0版本可以使用--clean参数,vim7.4版本似乎没有这么参数,所以还是更新一下vim到新版本。

 

三、vim运行时加载的搜索路径

为了确定启动时或加载缓冲区时会运行哪些脚本,Vim会遍历“runtimepath”。该设置是一组以逗号分隔的目录列表,各个目录的结构都是一致的。Vim会检查每个目录的结构,找到需要运行的脚本,并按照目录在列表中的顺序一一处理。本文会以window上的vim和Linux上面的vim作为比较来说明:

运行以下命令就可以检查系统上的runtimepath:

3.1 遍历搜索路径runtimepath

启动一个vim之后,执行

:set runtimepath

(1)在window下面得到的结果如下

runtimepath=
~/vimfiles,
~/vimfiles/after,
D:\Program Files (x86)\Vim\vim81,      # 这后面三个其实就是vim的安装目录之下的目录
D:\Program Files (x86)\Vim/vimfiles,
D:\Program Files (x86)\Vim/vimfiles/after

# 顺序我适当的调整了一下,当前用户目录之下的 vimfiles 类似于Linux下面的 .vim 文件夹,需要自己手动创建,否则是没有的。另外我window上面还没有安装其他的任何自定义插件,所以这里可能和后面的Linux的结果有所差别

(2)在Linux下面得到的结果

runtimepath=
~/.vim,                   # 前面这5个是自己安装的插件python-mode和nerdtree
~/.vim/after,
~/.vim/plugged/nerdtree/,
~/.vim/plugged/python-mode/,
~/.vim/plugged/python-mode/after,
/usr/share/vim/vim74,      #这后面三个同样是vim的安装路径之下的三个目录,这里是vim7.4版本
/usr/share/vim/vimfiles,
/usr/share/vim/vimfiles/after,

# 这里的顺序有所调整

比较发现,其实不管是Linux还是windows上面的vim其实运行时搜索路径(runtimepath)都是一样的结构

 

3.2 runtimepath包含的目录简介

runtimepath默认包含以下目录。并非所有这些都必须出现在文件系统中,但如果存在就会被使用。

  • ~/.vim

    主目录,保存个人偏好的文件。

  • /usr/local/share/vim/vimfiles

    系统范围的Vim目录,保存由系统管理员决定的文件。

  • /usr/local/share/vim/vim81

    即$VIMRUNTIME,保存与Vim一起分发的文件。

  • /usr/local/share/vim/vimfiles/after

    系统范围Vim目录中的“after”目录。系统管理员可以利用该目录来覆盖默认设置,或添加新的设置。

  • ~/.vim/after

    主目录中的“after”目录。可以利用该目录用个人偏好覆盖默认设置或系统设置,或添加新的设置。

这些目录会按照顺序处理,所以要说“after”目录有什么特别的话,那就是它位于列表末尾。实际上“after”并没有什么特别之处。

在处理每个目录时,Vim都会查找具有特定名称的子文件夹。如果想了解更多这方面的信息,

请参阅:help runtimepath。下面我们只挑部分进行说明。

  • plugin/

    编辑任何类型的文件都会自动加载的Vim脚本文件,称为“全局插件”。

  • autoload/

    (不要与“插件”相混淆。)自动加载中的脚本包含仅在其他脚本请求时加载的函数。

  • ftdetect/

    用于检测文件类型的脚本。可以根据文件扩展名、位置或内部文件内容决定文件类型。

  • ftplugin/

    编辑已知类型的文件时执行的脚本。

  • compiler/

    定义如何运行各种编译器或格式化工具,以及如何解析其输出。可以在多个ftplugins之间共享。且不会自动执行,必须通过 :compiler 调用。

  • pack/

    Vim 8原生软件包的目录,它采用了“Pathogen”格式的包管理。原生的包管理系统不需要任何第三方代码。

注意:

(1)上面的那些runtimepath文件夹下面可能包含上面的文件夹中的一个或者是几个,不一定全部包含,每一个文件夹的含义已经有所说明了;

(2)最后,通用的编辑器设置都会放到~/.vimrc中。你可以通过它来设置用于覆盖特定文件类型的默认值。有关.vimrc设置的全面讲解,请运行 :options

 

三、自定义安装第三方插件——vim的插件的本质是脚本

在Vim中,插件只是脚本,必须放在runtimepath中的正确位置才能执行。从概念上讲,插件的安装非常简单:只需下载文件。问题在于,很难删除或更新某些插件,因为它们的子目录加入到了runtimepath中,很难判断哪个插件负责哪些文件。

为了满足这种需求,网上出现了很多插件管理器。最早在2003年就出现了Vim.org插件仓库。然而,直到2008年左右,插件管理器的概念才真正流行起来。

这些工具在Vim的runtimepath中添加了单独的查检目录,并会为插件文档编译帮助标签。大多数插件管理器还可以从网上安装和更新插件代码,有的还支持并行更新,或者显示彩色的进度条。

以下是按时间顺序整理的插件管理器。我按照每个插件最早和最新版本进行了排序,如果找不到官方的发行版本,则根据最早和最后的提交日期排序。

  1. 2006年3月- 2014年7月:Vimball(分发格式和关联的Vim命令)

  2. 2008年10月- 2015年12月:Pathogen(由于原生vim包被弃用)

  3. 2009年8月- 2009年12月:Vimana

  4. 2009年12月- 2014年12月:VAM

  5. 2010年8月 - 2010年12月:Jolt

  6. 2010年10月 - 2012年12月:tplugin

  7. 2010年10月 - 2014年2月:Vundle(在NeoBundle破解代码后停止使用)

  8. 2012年3月 - 2018年3月:vim-flavor

  9. 2012年4月 - 2016年3月:NeoBundle(被弃用,建议使用dein)

  10. 2013年1月 - 2017年8月:infect

  11. 2013年2月 - 2016年8月:vimogen

  12. 2013年10月 - 2015年1月:vim-unbundle

  13. 2013年12月 - 2015年7月:Vizardry

  14. 2014年2月 - 2018年10月:vim-plug

  15. 2015年1月 - 2015年10月:enabler

  16. 2015年8月 - 2016年4月:Vizardry 2

  17. 2016年1月 - 2018年6月:dein.vim

  18. 2016年9月 - 至今:原生Vim 8

  19. 2017年2月 - 2018年9月:minpac

  20. 2018年3月 - 2018年3月:autopac

  21. 2017年2月 - 2018年6月:pack

  22. 2017年3月 - 2017年9月:vim-pck

  23. 2017年9月 - 2017年9月:vim8-pack

  24. 2017年9月 - 2019年5月:volt

  25. 2018年9月 - 2019年2月:vim-packager

  26. 2019年2月 - 2019年2月:plugpac.vim

首先要注意,这些工具五花八门,其次通常每个工具在活跃大约四年后就会过时。

 

五、vim 8的内置功能

最稳定的管理插件的方法是使用Vim 8的内置功能,该功能不需要第三方代码。下面让我们具体来看看这种方法。

首先在用户目录之下创建一个pack目录,然后在pack目录中创建两个子目录opt和start。注意这里,这里的自定义名称是我们要对插件进行的一个分类,比如自动补全的、导航的、调试的等等,方便管理,当然我就统统放在一个目录之下也行,只是不方便管理。

mkdir -p ~/.vim/pack/自定义名称/{opt,start}

注意事项:

(1)注意占位符 自定义名称。这个名称完全取决于你。我们用它对包进行分类。大多数人会把所有的插件都扔进一个无意义的类别中,这样完全没问题。你可以选择自己喜欢的名称,在本文中我选择使用 foobar。理论上,你也可以创建多个类别,比如~/.vim/pack/navigation, ~/.vim/pack/linting等,当然我也可以都放在foobar 这个目录之下。

(2)Vim不会检测类别之间的重复,如果存在重复,则会加载两次

(3)“start”目录中的包会自动加载。而对于“opt”目录中的包,只有通过:packadd命令特别请求,Vim才会加载。opt中适合保存不常用的软件包,以及为保持Vim的快速启动不必要运行的脚本。请注意,:packadd没有相反的命令卸载包。

在下述示例子中,我们将添加“ctrlp”模糊查找插件到opt目录。下载最新版本的命令如下:

curl -L https://github.com/kien/ctrlp.vim/archive/1.79.tar.gz \
    | tar zx -C ~/.vim/pack/foobar/opt  #解压到刚创建的opt文件夹之下

该命令创建了 ~/.vim/pack/foobar/opt/ctrlp.vim-1.79 文件夹,现在这个包可以使用了。我们再次回到vim中,为这个新包创建一个帮助标签的索引:

:helptags ~/.vim/pack/foobar/opt/ctrlp.vim-1.79/doc

该命令会在刚安装的ctrlp-1.79目录包的doc目录中创建了一个名叫”tags“的文件,这样Vim的内部帮助系统就可以使用它的内容了。(或者你也可以在包加载之后运行一次:helptags ALL,该命令会处理runtimepath下的所有文档。)

在需要使用包时,只需加载它(Tab自动补齐也可以用于插件名,所以不需要输入全名):

下面在启动vim之后,选择性的加载opt目录之下的插件

:packadd ctrlp.vim-1.79

packadd会把包的根目录放到runtimepath中,然后运行它的plugin和ftdetect脚本。在加载ctrlp之后,就可以按Ctrl-P来弹出模糊文件查找了。

 

  • 14
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值