DEV Community

fengzhao
fengzhao

Posted on

dive-into-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加载时加载了那些插件(执行了哪些脚本)
:scriptnames 

  1: /usr/share/vim/vimrc
  2: /usr/share/vim/vim81/debian.vim
  3: /usr/share/vim/vim81/syntax/syntax.vim
  4: /usr/share/vim/vim81/syntax/synload.vim
  5: /usr/share/vim/vim81/syntax/syncolor.vim
  6: /usr/share/vim/vim81/filetype.vim
  7: ~/.vim/ftdetect/nginx.vim
  8: ~/.vimrc
  9: /usr/share/vim/vim81/colors/space-vim-dark.vim
 10: /usr/share/vim/vim81/plugin/getscriptPlugin.vim
 11: /usr/share/vim/vim81/plugin/gzip.vim
 12: /usr/share/vim/vim81/plugin/logiPat.vim
 13: /usr/share/vim/vim81/plugin/manpager.vim
 14: /usr/share/vim/vim81/plugin/matchparen.vim
 15: /usr/share/vim/vim81/plugin/netrwPlugin.vim
 16: /usr/share/vim/vim81/plugin/rrhelper.vim
 17: /usr/share/vim/vim81/plugin/spellfile.vim
 18: /usr/share/vim/vim81/plugin/tarPlugin.vim
 19: /usr/share/vim/vim81/plugin/tohtml.vim
 20: /usr/share/vim/vim81/plugin/vimballPlugin.vim
 21: /usr/share/vim/vim81/plugin/zipPlugin.vim
 22: /usr/share/vim/vim81/scripts.vim
 23: /usr/share/vim/vim81/syntax/vim.vim
 24: /usr/share/vim/vim81/syntax/python.vim
 25: ~/.vim/plugged/vim-airline/plugin/airline.vim
 26: ~/.vim/plugged/vim-airline/autoload/airline/init.vim
 27: ~/.vim/plugged/vim-airline/autoload/airline/parts.vim
 28: ~/.vim/plugged/vim-airline/autoload/airline/util.vim
 29: ~/.vim/plugged/vim-easy-align/plugin/easy_align.vim
Enter fullscreen mode Exit fullscreen mode

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

这其实也就是vim在启动的时候会加载脚本,脚本越多就越耗时间。如果你安装了大量插件的话,那么编辑器需要做大量工作。

查看 vim 启动时间

vim --startuptime start.log test1.py
Enter fullscreen mode Exit fullscreen mode

打开这个 test1.py 文件的同时,生成一个 start.log 的日志文件:

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

000.014  000.014: --- VIM STARTING ---
000.415  000.401: Allocated generic buffers
000.717  000.302: locale set
000.734  000.017: window checked
001.838  001.104: inits 1
002.059  000.221: parsing arguments
002.063  000.004: expanding arguments
002.094  000.031: shell init
002.794  000.700: Termcap init
002.844  000.050: inits 2
003.193  000.349: init highlight
006.708  002.160  002.160: sourcing /usr/local/share/vim/vim82/syntax/syncolor.vim
007.073  002.654  000.494: sourcing /usr/local/share/vim/vim82/syntax/synload.vim
021.470  014.263  014.263: sourcing /usr/local/share/vim/vim82/filetype.vim
021.561  017.365  000.448: sourcing /usr/local/share/vim/vim82/syntax/syntax.vim
021.671  000.022  000.022: sourcing /usr/local/share/vim/vim82/filetype.vim
022.298  000.327  000.327: sourcing /usr/local/share/vim/vim82/syntax/syncolor.vim
023.018  000.311  000.311: sourcing /usr/local/share/vim/vim82/syntax/syncolor.vim
023.498  000.315  000.315: sourcing /usr/local/share/vim/vim82/syntax/syncolor.vim
024.292  002.567  001.614: sourcing /root/.vim/colors/molokai.vim
027.588  003.206  003.206: sourcing /root/.vim/autoload/plug.vim
031.007  001.300  001.300: sourcing /usr/local/share/vim/vim82/ftoff.vim
044.017  000.408  000.408: sourcing /root/.vim/plugged/vim-go/ftdetect/gofiletype.vim
044.226  011.661  011.253: sourcing /usr/local/share/vim/vim82/filetype.vim
044.435  000.064  000.064: sourcing /usr/local/share/vim/vim82/ftplugin.vim
044.607  000.054  000.054: sourcing /usr/local/share/vim/vim82/indent.vim
044.775  041.278  005.039: sourcing $HOME/.vimrc
044.785  000.314: sourcing vimrc file(s)
045.472  000.173  000.173: sourcing /root/.vim/plugged/vim-airline/autoload/airline/init.vim
046.018  000.142  000.142: sourcing /root/.vim/plugged/vim-airline/autoload/airline/parts.vim
047.723  000.339  000.339: sourcing /root/.vim/plugged/vim-airline/autoload/airline/util.vim
047.793  002.877  002.223: sourcing /root/.vim/plugged/vim-airline/plugin/airline.vim
048.251  000.357  000.357: sourcing /root/.vim/plugged/vim-easy-align/plugin/easy_align.vim
048.429  000.084  000.084: sourcing /root/.vim/plugged/neodark.vim/plugin/neodark.vim
049.881  001.103  001.103: sourcing /root/.vim/plugged/vim-go/autoload/go/config.vim
051.495  000.824  000.824: sourcing /root/.vim/plugged/vim-go/autoload/go/util.vim
...
...
中间省略
...
...
084.259  000.044  000.044: sourcing /root/.vim/plugged/vim-airline/autoload/airline/extensions/keymap.vim
091.665  000.092  000.092: sourcing /root/.vim/plugged/vim-airline/autoload/airline/themes.vim
092.103  000.665  000.573: sourcing /root/.vim/plugged/vim-airline/autoload/airline/themes/dark.vim
120.187  000.269  000.269: sourcing /root/.vim/plugged/vim-airline/autoload/airline/builder.vim
120.828  000.132  000.132: sourcing /root/.vim/plugged/vim-airline/autoload/airline/extensions/default.vim
190.934  110.326: opening buffers
190.988  000.054: BufEnter autocommands
191.000  000.012: editing files in windows
191.559  000.559: VimEnter autocommands
191.561  000.002: before starting main loop
194.803  003.242: first screen update
194.806  000.003: --- VIM STARTED ---
Enter fullscreen mode Exit fullscreen mode

可以看到,用 vim 打开这个 test1.py 文件,花费了 194.806 毫秒。

干净的启动vim(不带任何插件的启动)

#  --clean  'nocompatible', Vim defaults, no plugins, no viminfo,
#  即仅仅使用默认的vim设置,不加载插件,也不启用其它的vimrc的配置等。
#  vim8.0版本可以使用--clean参数,vim7.4版本似乎没有这么参数,所以还是更新一下vim到新版本
vim --clean --startuptime start3.log test1.py
Enter fullscreen mode Exit fullscreen mode

打开 start3.log,发现总共耗时 022.682 毫秒。

...
省略前面的
...
022.208  000.032: VimEnter autocommands
022.209  000.001: before starting main loop
022.680  000.471: first screen update
022.682  000.002: --- VIM STARTED ---
Enter fullscreen mode Exit fullscreen mode

vim运行时加载的搜索路径

为了确定启动时或加载缓冲区时会运行哪些脚本,Vim会遍历 'runtimepath'。该设置是一组以逗号分隔的目录列表,各个目录的结构都是一致的。

Vim会检查每个目录的结构,找到需要运行的脚本,并按照目录在列表中的顺序一一处理。

遍历搜索路径runtimepath

启动一个vim之后,执行

:set runtimepath
Enter fullscreen mode Exit fullscreen mode

得到结果:

  runtimepath=~/.vim,
  ~/.vim/plugged/vim-airline,
  ~/.vim/plugged/vim-easy-align,
  ~/.vim/plugged/neodark.vim,
  ~/.vim/plugged/vim-monokai,
  ~/.vim/plugged/vim-colors-github,
  ~/.vim/plugged/vim-one,
  ~/.vim/plugged/vim-go,
  ~/.vim/plugged/vim-godef,
  ~/.vim/plugged/nerdtree,
  ~/.vim/plugged/vim-nerdtree-tabs,
  ~/.vim/plugged/nerdtree-git-plugin,
  /usr/local/share/vim/vimfiles,
  /usr/local/share/vim/vim82,
  /usr/local/share/vim/vimfiles/after,
  ~/.vim/after
Enter fullscreen mode Exit fullscreen mode

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”格式的包管理。原生的包管理系统不需要任何第三方代码。

自定义安装第三方插件

vim的插件的本质是脚本,在Vim中,插件只是脚本,必须放在runtimepath中的正确位置才能执行。

vim插件管理工具

vim8 native package manager

最稳定的管理插件的方法是使用Vim8的内置的 native package manager功能,该功能不需要第三方代码。

首先在用户目录之下的.vim文件夹之下创建一个pack目录,然后在pack目录中创建两个子目录opt和start。

注意这里,这里的自定义名称是我们要对插件进行的一个分类,比如自动补全的、导航的、调试的等等,方便管理,当然我就统统放在一个目录之下也行,只是不方便管理。

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

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

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

Top comments (1)

Collapse
 
gaoryrt profile image
gaoryrt

兄弟,发 segmentfault 都比这儿好