LV02-vimscript-09-插件.md
本文主要是vimscript一些基础知识和操作的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows | windows11 |
Ubuntu | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
点击查看本文参考资料
参考方向 | 参考原文 |
Learn vimscript the Hard Way | https://learnvimscriptthehardway.stevelosh.com/ |
vim在线文档 | http://vimcdoc.sourceforge.net/ |
VIM 中文帮助 | https://vimcdoc.sourceforge.net/doc/help.html |
vim教程 | https://www.w3cschool.cn/vim/ |
一、插件
插件,我们应该并不陌生,软件插件会给我们带来更好的使用体验。vim
中也有很多的插件,有很多会提高我们的工作效率。
当没有插件管理器时,我们必须手动下载tarball
包形式的插件,并将它们解压到 ~/.vim
目录中。在少量插件的时候可以。但当安装很多的插件时,这就会变得一团糟,尤其是更新的时候,简直无法想象。所有插件文件分散在单个目录中,我们根本无法找到哪个文件属于哪个插件。此外,我们当然也无法找到应该删除哪个文件来卸载不想要的插件。
这时 vim
插件管理器就为我们带来了极大的便利。插件管理器将安装插件的文件保存在单独的目录中,因此管理所有插件变得非常容易。
二、插件管理器
vim
中有一些插件管理器,我们可以通过插件管理器来安装和管理插件,我一般常用的有两种,一个是vim-plug
,另一个是Vundle
1. vim-plug
1.1 简介
vim-plug
是一个自由、开源、速度非常快的、极简的 vim
插件管理器。我自己用的也是这一个,那它有什么特点呢?
- 可以并行地安装或更新插件。
- 可以回滚更新。
- 创建浅层克隆shallow clone最小化磁盘空间使用和下载时间。
- 支持按需加载插件以加快启动时间。
- 支持分支/标签/提交、post-update 钩子、支持外部管理的插件等。
不过要注意的是,这个插件源码仓库是在GitHub
上的,很有可能不能访问,此时科学上网一下就可以了。
vim-plug
仓库地址
1 | https://github.com/junegunn/vim-plug # GitHub 仓库 |
1.2 安装vim-plug
- 通过
curl
安装
1 | curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ |
- 直接安装
1 | mkdir -p ~/.vim/autoload/ |
然后可以通过下载源码的方式将压缩包下载下来,将其中的plug.vim
放入刚才创建的文件夹即可。
1.3 安装插件
- 创建插件安装目录
1 | cd ~/.vim |
- 修改
~/.vimrc
文件
将要安装的插件仓库名称写入到~/.vimrc
中,按以下格式即可:
1 | " ~/.vim/plugged 为插件安装目录 |
- 安装插件
在任意vim
窗口中,进入命令模式,然后执行以下命令:
1 | :PlugInstall |
然后,vim
就会开始安装插件,不过就是这些似乎经常安装失败,最好就是科学上网,这样会好点。
这样,我们写在~/.vimrc
中的插件就会被安装了,安装的目录为/home/hk/.vim/plugged
,每个插件都会有一个单独的目录:
1.4常用命令
PlugInstall [name ...] [#threads] | Install plugins |
PlugUpdate [name ...] [#threads] | Install or update plugins |
PlugClean[!] | Remove unlisted plugins (bang version will clean without prompt) |
PlugUpgrade | Upgrade vim-plug itself |
PlugStatus | Check the status of plugins |
PlugDiff | Examine changes from the previous update and the pending changes |
PlugSnapshot[!] [output path] | Generate script for restoring the current snapshot of the plugins |
2. Vundle
2.1 简介
Vundle
是 vim bundle
的简称,Vundle
为每一个安装的插件创建一个独立的目录树,并在相应的插件目录中存储附加的配置文件。因此,相互之间没有混淆的文件。简言之,Vundle
允许我们安装新的插件、配置已有的插件、更新插件配置、搜索安装的插件和清理不使用的插件。
Vundle
仓库地址
1 | https://github.com/VundleVim/Vundle.vim " GitHub 仓库 |
2.2 安装Vundle
- 安装
git
1 | sudo apt-get install git |
clone
仓库
1 | git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim |
1 | git clone https://gitee.com/jason_lkm/Vundle.vim.git ~/.vim/bundle/Vundle.vim |
2.3 安装插件
- 修改
~/.vimrc
文件
将要安装的插件仓库名称写入到~/.vimrc
中,按以下格式即可:
点击查看格式
1 | set nocompatible " 去除VI一致性,必须 |
- 安装插件
在任意vim
窗口中,进入命令模式,然后执行以下命令:
1 | :PlugInstall |
或者直接在终端执行以下命令也可以:
1 | vim +PluginInstall +qall |
2.4 常用命令
😓我用vim-plug
来管理插件,所以这个插件的相关命令没有试过吗,这里就暂时先不写了。
三、以前的插件配置
上边我们了解了插件管理器,那么没有插件管理器的时候是怎样的呢?这对我们了解插件的结构有很大的帮助。vim
支持把插件分割成多个文件,我们可以在~/.vim
下创建许多不同种类的文件夹来放置不同的内容。接下来我们就来了解一下一些重要文件夹作用。
1. ~/.vim/colors/
vim
将会查找~/.vim/colors/mycolors.vim
并执行它。 这个文件应该包括生成插件配色方案所需的一切vimscript
命令。
2. ~/.vim/plugin/
~/.vim/plugin/
下的文件将在每次vim
启动的时候执行。 这里的文件包括那些无论何时,在启动vim
之后就想加载的代码。
3. ~/.vim/ftdetect/
~/.vim/ftdetect/
下的文件在每次启动vim的时候也会执行。ftdetect
是filetype detection
的缩写。 这里的文件仅仅负责启动检测和设置文件的filetype
类型的自动命令。 这意味着它们一般不会超过一两行。
4. ~/.vim/ftplugin/
~/.vim/ftplugin/
下的文件则各不相同。一切皆取决于它的名字。当vim
把一个缓冲区的filetype
设置成某个值时, 它会去查找~/.vim/ftplugin/
下对应的文件。 比如:如果我们执行set filetype=derp
,vim
将查找~/.vim/ftplugin/derp.vim
。 一旦文件存在,vim
将执行它。
vim
也支持在~/.vim/ftplugin/
下放置文件夹。 再以我们刚才的例子为例:set filetype=derp
将告诉vim
去执行~/.vim/ftplugin/derp/
下的全部*.vim
文件。 这使得我们可以按代码逻辑分割在ftplugin
下的文件。
因为每次在一个缓冲区中执行filetype
时都会执行这些文件,所以它们只能设置buffer-local
选项。 如果在它们中设置了全局选项,所有打开的缓冲区的设置都会遭到覆盖!
5. ~/.vim/indent/
~/.vim/indent/
下的文件类似于ftplugin
下的文件。加载时也是只加载名字对应的文件。
indent
文件应该设置跟对应文件类型相关的缩进,而且这些设置应该是buffer-local
的。我们当然可以把这些代码也一并放入ftplugin
文件, 但最好把它们独立出来,让其他vim
用户理解插件开发者的意图。这只是一种惯例,不过还是尽量体贴用户并遵从它。
6. ~/.vim/compiler/
~/.vim/compiler
下的文件非常类似于indent
文件。它们应该设置同类型名的当前缓冲区下的编译器相关选项。
7. ~/.vim/after/
~/.vim/after
文件夹有点神奇。这个文件夹下的文件会在每次vim
启动的时候加载, 不过是在~/.vim/plugin/
下的文件加载了之后。
这允许我们覆盖vim
的默认设置。实际上我们将很少需要这么做,所以不用理它, 除非我们有vim
设置了选项x
,但又想要不同的设置的主意。
8. ~/.vim/autoload/
~/.vim/autoload
文件夹就更加神奇了。事实上它的作用没有听起来那么复杂。简单地说:autoload
是一种延迟插件代码到需要时才加载的方法,后边会有详细介绍。
9. ~/.vim/doc/
~/.vim/doc/
文件夹提供了一个我们可以放置的插件的文档的地方。 vim
对文档的要求是多多益善(看看我们执行过的所有:help
命令就知道),所以为我们的插件写文档是非常重要的。
四、自动加载
还记得刚才说的autoload
目录吧,这个目录下的文件很有用,接下来就让我们来了解一下吧。
虽然我还没有开发过vim
的插件,但是我很乐意了解一下这个自动加载的功能,这样也许我可以更加容易的看懂插件,从而修改自己不喜欢的地方。自动加载有什么用?简单来说就是可以让我们的插件效率更高。
想象一下,当我们打开vim
的时候,某个插件有很多的功能,可是那个功能我们很少用到,但是它一开始的时候就直接进行了加载,这不仅会很浪费时间吗,也会很浪费内存。我自己觉得就跟Windows
系统下的开机自启动一样,有些软件我们基本不用,但是如果设置了开启启动,它就会拖慢我们的开机速度,在后台的时候也会占用内存,为什么不能不让它开启自启,我想用的时候在打开不好吗?自动加载大概就是这个意思吧。
vim
中自动加载让我们直到需要时才加载某一部分代码。 这会有一些性能上的损失,但如果我们不总是需要那个插件的每一行代码,自动加载将带来速度上的飞跃。
接下来就让我们一起来探索一下它是如何工作的。
1. 如何定义函数?
在命令模式下尝试执行:
1 | :call plugfile#Hello() |
执行这个命令的时候,当然我们只是尝试,这个函数还没有定义,一定会报错的,这里只是一个示例。
在这里vim
的行为与平常的函数调用有些许不同,如果这个函数已经加载了,vim
简单地像平常一样调用它。但是若是函数并未加载,那么vim
将在~/.vim
(或~/.vim/plugged/plug_name/autoload
)下查找一个叫做autoload/plugfile.vim
的文件。如果文件存在,vim
将加载这个文件,接着vim就会像平常一样调用它。
这里有一条关于文件位置的说明
【说明】这里只是因为我的插件安装在~/.vim/plugged
下,所以是这个目录,要是使用其他插件管理器的话可能在其他目录中,这里只是提供一个实例,比如我的airline
插件:
在这个文件中,函数的定义应该是这样的格式:
1 | function plugfile#Hello() |
点击查看对 # 的说明
这里函数名中的#
表示子目录,我们可以使用多个#
来表示目录层级关系,例如
1 | :call myplugin#plugfile#Hello() |
那么,vim
将会在autoload/myplugin/plugfile.vim
查找自动加载文件。 里面的函数需要使用自动加载的绝对路径进行定义:
1 | function myplugin#plugfile#Hello() |
2. 开始实践
- 创建文件
让我们创建~/.vim/autoload/test.vim
文件:
1 | vim ~/.vim/autoload/test.vim |
在文件中添加以下内容:
1 | echo "Loading..." |
然后通过:wq
命令保存文件并退出。
- 保存并载入文件
当我们没有通过source
命令载入~/.vim/autoload/test.vim
脚本文件的时候,这个脚本文件是不会生效的,随便打开一个vim
窗口,在命令模式中执行:
1 | :source ~/.vim/autoload/test.vim |
source %
命令表示载入该脚本,此时输出结果如下:
1 | Loading... |
有两行输出结果,这说明这个脚本已经通过source
命令被载入并生效了。
- 调用函数载入文件
首先关闭刚才的vim
窗口,使刚才生效的脚本文件失效。然后重新打开一个vim
窗口(任意一个即可),在命令模式中执行:
1 | :call test#Hello() |
输出结果如下:
1 | Loading... |
这说明了什么?当我们打开一个vim
窗口的时候,~/.vim/autoload/test.vim
脚本文件并没有打印出以下内容:
1 | Loading... |
这就说明脚本文件并没有生效,并没有被载入。而当我们执行了刚才的函数调用命令后,vim
在调用函数之前加载了整个文件,所以加上调用函数的输出,一共有三行的输出。同时也证明了,刚才的脚本文件在调用函数的时候才被加载。
- 修改文件会发生什么?
首先我们开测试脚本文件:
1 | vim ~/.vim/autoload/test.vim |
然后在命令模式中执行:
1 | :call test#Hello() |
这样,就会通过自动加载而载入整个文件,输出结果如下:
1 | Loading... |
接下来,我们不要关闭vim
,直接修改函数内容为:
1 | echo "Loading..." |
然后在命令模式中执行:
1 | :w " 保存文件 |
会发现输出结果如下:
1 | Hello, world! |
仅仅只有一行输出,还是脚本文件修改前的输出情况。这是为什么呢?我的文件明明修改并保存了呀。vim
已经有了test#Hello
的一个定义,所以它不再需要重新加载文件,这意味着:
(1)函数以外的代码将不再执行。
(2)它不会反映函数本身的变化。