美文网首页Vim
Vim 插件管理器 - dein.vim

Vim 插件管理器 - dein.vim

作者: Whyn | 来源:发表于2020-06-06 12:09 被阅读0次

    前言

    vim-plug 是一个非常优秀的 Vim 插件管理器,但是随着安装的插件越来越多,逐渐发现即使使用 vim-plug,首次启动速度仍然很慢。

    究其原因,虽然 vim-plug 本身提供了优秀的延迟加载机制,但是可用于延迟加载的选项相对较少,另一方面,vim-plug 对插件的延迟加载与配置无法进行统一,很多时候,我们想对插件进行延迟加载,但是插件配置项如果调用了插件功能,则加载的时候就会报错(因为插件此时还未加载)...

    针对上述问题,dein.vim 都给出了更优秀的解决方案。

    vim-plug 是一款非常优秀的插件管理器,具备优秀的插件管理性能,同时操作及其简单,且具备优秀的 UI 显示,通常情况下,建议使用 vim-plug
    但是如果当使用 vim-plug 后,启动速度仍然很慢,那就可以考虑下 dein.vim

    dein 本身只提供函数接口进行操作,没有提供命令与 UI 显示,对于用户相对不友好。
    不过 Github 上面已经有人对其进行了再一次封装:

    可以结合以上两个插件,简化 dein 使用。

    优点

    • 启动快
    • 支持异步安装
    • 支持本地插件
    • 支持多种 VCS(包括 git)
    • 支持缓存
    • 支持merge特性,有效减少runtimepath层级
      ...

    安装

    • 对于 Unix/Linux/Mac:
    curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
    # 安装路径我们选择:~/.vim/dein
    sh ./installer.sh ~/.vim/dein
    
    • 对于 Windows:
    Invoke-WebRequest https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.ps1 -OutFile installer.ps1
    # Allow to run third-party script
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
    # 安装路径我们选择:~/.vim/dein
    ./installer.ps1 ~/.vim/dein
    

    dein 基本使用

    • 最简配置:基本结构如下:
    if &compatible
        set nocompatible
    endif
    
    let s:dein_path = '~/.vim/dein'
    
    " Add the dein installation directory into runtimepath
    let &runtimepath = &runtimepath.','.s:dein_path.'/repos/github.com/Shougo/dein.vim'
    
    if dein#load_state(s:dein_path)
      call dein#begin(s:dein_path)
    
      call dein#add(s:dein_path.'/repos/github.com/Shougo/dein.vim')
    
      " install third-party plugins
      " call dein#add('tpope/vim-surround')
    
      call dein#end()
      call dein#save_state()
    endif
    
    filetype plugin indent on
    syntax enable
    
    • 插件安装:插件基本安装方法如下:

      1. dein#begin()dein#end()之间使用dein#add({plugin})声明要安装的插件:
      call dein#begin(s:dein_path)
      
      " install third-party plugins
      call dein#add('tpope/vim-surround')
      
      call dein#end()
      
      1. 重新打开 Vim 或者手动重新加载配置:so %后,使用如下命令安装插件:
      :call dein#install()
      

      :由于 dein 没有 UI 显示下载进度,需等待一段时间,等下载完成后,底部提示栏会有显示通知。
      也可以直接到<dein_path>/repos/查看插件是否已安装完成。

      1. 关闭 Vim,再重新打开,就可以使用已安装的插件功能了。
    • 插件卸载:dein.vim 并未直接提供插件卸载功能,因此其插件卸载相对麻烦,步骤如下:

      1. 取消插件添加配置:将要卸载的插件进行注释:
      call dein#begin(s:dein_path)
      
      " uninstall vim-surround
      " call dein#add('tpope/vim-surround')
      
      call dein#end()
      
      1. 清除缓存:关闭再重新打开 Vim,执行:call dein#recache_runtimepath()
        :由于 dein 采用了merge功能,其会将所有插件的plugin/目录下的内容都缓存到同一个目录(具体为<dein_path>/.cache/init.vim/.dein/plugin)中,因此虽然我们上一步配置文件取消了添加插件,但由于缓存未删除,导致本次启动仍然会加载相应插件,故还需手动进行缓存清除操作。

      2. 关闭再重新打开 Vim,就可以发现插件功能已禁止(可选)

      3. 删除插件:以上操作只是停用了插件,插件仍然存在于本地电脑,如果想进行删除,还需调用如下命令:

      :call map(dein#check_clean(), "delete(v:val, 'rf')")
      

      此时就可以看到 dein 目录下的repo下的相应插件被删除了,缓存文件夹.cache下的.dein/plugin相关的插件缓存也被删除了。

    • 失能插件:不删除插件,只是不进行加载,步骤如下:

      1. 将配置文件中的dein#add改为dein#disable,如下所示:
      call dein#begin(s:dein_path)
      
      call dein#add('tpope/vim-surround')
      " disable 添加到 add 后面
      call dein#disable('vim-surround')
      
      call dein#end()
      
      1. 关闭 Vim,再重新打开,执行:call dein#recache_runtimepath()

      2. 关闭 Vim,再重新打开,就可以看到插件功能禁止了。

    :以上任何操作如果失败,一律进行如下操作,确保不受 dein 缓存机制影响:

    1. 重新打开 Vim,执行:call dein#clear_state(),清除状态文件,强制 dein 重新加载配置。
    2. 退出后重新打开 Vim,执行:call dein#recache_runtimepath(),清除旧缓存
    3. 退出 Vim,再重新打开,执行剩余操作

    一些有用操作/设置

    在对 dein 进行详细介绍前,先了解下其提供的一些比较有用的操作/设置,方便理解与使用。

    • 手动安装插件:依次输入以下命令:
    " 开始块,安装路径可以自由更改
    :call dein#begin('~/.cache/dein') 
    " 添加插件安装声明
    :call dein#add('~/.vim/plugB')
    " 配置块结束,安装自动开始
    :call dein#end()
    
    • 手动加载插件:dein#source([{plugins}])
    :call dein#source('vim-surround')
    

    dein#source会直接加载插件,无论插件是否配置了懒加载。

    • 检测插件是否已安装:dein#check_install({plugins})

      • 返回0:表示插件已安装,可以正常使用
      • 返回-1:表示是无效插件
      • 返回其他:表示插件未安装
      :call dein#check_install('vim-surround')
      
    • 检测插件是否已加载:dein#is_sourced({plugin-name})

      • 返回0:表示插件未加载
      • 返回其他:表示插件存在且已加载
      :call dein#is_sourced('vim-surround')
      

      :由于 dein 存在懒加载,因此存在插件已安装(dein#check_install)但未加载(dein#is_sourced)的情形。

    • 检测插件是否被禁用:dein#tap({plugin-name})

      • 返回0:表示插件不存在,或者被禁用
      • 返回其他:表示插件存在,且可以使用(懒加载插件在未加载前也是属于可以使用状态)
      :call dein#tap('vim-surround')
      
    • 插件懒加载

    call dein#add('junegunn/fzf', {
        \'lzay': 1,                                               " 非0 表示启用懒加载
        \ 'if': s:has_exec('fzf'),                                " 条件满足时才加载(判断类型`String`/`Number`)
        \ 'on_if': 'winnr("$") > 1',                              " 条件满足时才加载(判断类型`String`)
        \ 'on_cmd': 'FZF',                                        " 存在 FZF 命令时才加载
        \ 'on_func': 'fzf#run',                                   " 调用了函数 fzf#run 时才进行加载
        \ 'on_event': ['VimEnter', 'BufRead']                     " 事件发生时才加载
        \ 'on_ft': 'python'                                       " 文件类型匹配时才加载
        \ 'on_map': { 'n' : ['<C-n>', '<C-p>'], 'x' : '<C-n>'}} " 匹配特定模式下的按键映射时才加载
        \ 'on_path': '.editorconfig',                             " 路径匹配时才加载
        \ 'on_source':  ['vim-surround']                          " 插件 vim-surround 加载时才加载
        \ })
    

    :懒加载时lazy可忽略,dein 会自动根据其他选项自动判断是否启用懒加载。

    • 检测未使用的插件目录(可以清除):dein#check_clean()

    • 获取插件配置:dein#get([{plugin-name}])

    :echo dein#get('vim-surround')
    

    函数

    以下是 dein.vim 内置的函数简介:

    • dein#add({repo}[, {options}]):初始化/添加插件。

      • {repo}:表示插件 URI 或者插件本地路径。

      • {options}:对插件进行额外选项配置,具体选项请参考下文:选项(OPTIONS)

      dein#add必须在dein#begin()块中使用。

    • dein#begin({base-path}, [{vimrcs}]):初始化 dein.vim,开启插件配置块。

      • {base-path}:表示插件下载安装路径

      • {vimrcs}:额外配置选项或者 TOML 配置文件。默认值为$MYVIMRC

      :不能在has('vim_starting')块中调用dein#begin()
      dein#begin()会自动设置:filetype off

    • dein#build([{plugins}]):编译插件{plugins}

      :当使用类似dein#add('autozimu/LanguageClient-neovim', {'build': 'bash install.sh'})配置插件时,指定了build选项,则可通过调用:call dein#build()对插件进行重新编译安装,即执行bash install.sh

    • dein#call_hook({hook-name}):调用钩子函数{hook-name}

      :如果{hook-name}设置为source,那么 dein 就会触发已加载的插件的hook_source钩子函数。

    • dein#check_install({plugins}):查看插件是否已安装。

      • 对于已安装的插件{plugins},该函数返回0
      • 对于未安装的插件{plugins},该函数返回 非0 数值。
      • 对于无效插件,该函数返回 -1。
      • 如果{plugins}忽略不写,则对所有插件进行检测。
      " 已安装,则返回 0
      :echo dein#check_install('vim-surround')
      
    • dein#check_lazy_plugins():检测无意义的懒加载插件。

      插件如果没有plugin/目录,那么对这类插件进行懒加载是没有意义的。

    • dein#check_update([{plugins}]):异步检测插件是否可更新。

    • dein#check_clean():返回未使用的插件。可以结合其他命令手动进行删除。

    • dein#clear_state():手动清除状态文件。

      :状态文件的路径为:<dein_path>/state_vim.vim

    • dein#config({plugin-name}, {options})/dein#config({options}):修改插件配置选项。

      如果忽略{plugin-name},那么配置选项作用于全局变量g:dein#name指定的值。
      如果{plugin-name}是列表,那么一套相同的配置项就可以作用于多个插件。
      如果{plugin-name}已经加载,或者是无效状态,那么忽略该配置选项{options}

      call dein#add('Shougo/deoplete.nvim')
      call dein#config('deoplete.nvim', {
          \ 'lazy' : 1, 'on_i' : 1,
          \ })
      

      dein#config()必须在dein#begin()dein#end()块中调用。

    • dein#direct_install({repo}[, {options}]):下载插件,并直接进行加载(source),即不会加载配置块(dein#begin()/dein#end())选项。

      " 直接加载插件 deoplete.vim
      call dein#direct_install('Shougo/deoplete.nvim')
      

      dein#direct_install直接下载的插件配置文件存放于dein#get_direct_plugins_path(),我们可以手动加载更改该文件配置。

    • dein#disable({plugins}):失能/禁止加载插件。

      dein#disable()函数必须在相关插件加载之前进行使用。因为 Vim 默认机制在加载插件后,无法直接失能/禁止。

      call dein#add('skywind3000/asyncrun.vim')
      call dein#disable('asyncrun.vim')
      
    • dein#each({command}[, {plugins}]):为每个插件{plugins}执行{command}命令。

    • dein#end()dein 配置块结束位置。

      :如果使能了g:dein#auto_recache,那么dein#end()会自动执行dein#recache_runtimepath(),重新加载缓存。
      :在dein#end()执行后,runtimepath会被更改。

    • dein#get([{plugin-name}]):获取插件{plugin-name}配置选项。

      :echo dein#get('asyncrun.vim')
      

      :如果未指定{plugin-name},则返回所有插件信息。

    • dein#get_direct_plugins_path():获取直接下载安装插件脚本路径。

    • dein#get_log():获取插件安装日志信息。

    • dein#get_progress():获取当前更新进程信息。

    • dein#get_updates_log():打印插件更新日志。

    • dein#install([{plugins}]):异步安装插件。

      • {plugins}:指定插件名称。如果该参数未设置,则默认安装所有插件。
    • dein#is_sourced({plugin-name}):查询插件加载状态。返回任意非 0 值表示插件存在且已加载(source)。

      :更多相关信息,可参考::h dein#source():h dein#tap()

    • dein#load_dict({dict}, [{options}]):从字典{dict}中加载插件配置选项。

      • {dict}key为插件 URI,valuedein-options构成的字典。比如:
      call dein#load_dict({
          \ 'Shougo/denite.nvim': {},
          \ 'Shougo/deoplete.nvim': {'name': 'deoplete'}
          \ })
      
    • dein#load_rollback({rollbackfile}[, {plugins}]):以{rollbackfile}文件回滚插件。

      :这是一个危险命令。

    • dein#load_state({base-path}):从缓存脚本文件中加载 dein 状态信息。

      • {base-path}:为插件下载存放路径。
        如果该函数返回 1,则表示缓存脚本过期,或者无效,或者不存在。
      if dein#load_state(path)
          call dein#begin(path)
          " My plugins here:
          " ...
          call dein#end()
          call dein#save_state()
      endif
      

      dein 的状态缓存脚本存放路径为:dein#util#_get_runtime_path() . '/state_' . fnamemodify(v:progname, ':r') . '.vim',也即:<dein_path>/.cache/init.vim/.dein/state_nvim.vim:实践中发现,状态文件存储路径为:<dein_path>/state_nvim.vim
      dein#load_state()函数必须在dein#begin()前进行调用,因为它会清除 dein 的所有配置。
      dein#load_state()会完全覆盖runtimepath,因此在动态更改runtimepath后,千万不要调用该函数,否则前面的设置就无效了。
      :当 dein 的状态信息已被加载时,会自动跳过该块内容。

    • dein#load_toml({filename}, [{options}]):从{filename}文件中以 TOML 格式加载插件配置。

    • dein#local({directory}, [{options}, [{names}]]):添加{directory}的子目录到runtimepath

      {names}:为子目录的名称。如果指定了{names},那么 dein 就只会加载这些子目录(子目录可使用通配符匹配)。

      " Load plugin from "~/.vim/bundle".
      call dein#local("~/.vim/bundle")
      " Load plugin1 and plugin2 from "~/.vim/bundle".
      call dein#local("~/.vim/bundle", {},
      \ ['plugin1', 'plugin2', 'vim-*', '*.vim'])
      
    • dein#update([{plugins}]):安装/更新插件。

      dein#update()在 Vim 8.0+ 和 Neovim 中,会以异步方式执行。

    • dein#plugins2toml({plugins}):获取插件{plugins} TOML 格式的配置信息。

    • dein#reinstall({plugins}):重新安装插件。

    • dein#remote_plugins():加载尚未加载的远程插件remote-plugin,并执行命令:UpdateRemotePlugins

      dein#remote_plugins()只在 Neovim 中可用。

    • dein#rollback({date}[, {plugins}]):回滚到最接近{date}指定日期的插件版本。

      • {data}:如果设置为"",则回滚到插件最新版本。

      dein#rollback()是一个危险命令。

    • dein#recache_runtimepath():重新加载 deinruntimepath缓存目录,并执行:helptags。该命令会在安装完成后自动调用。

      dein 中使用了一种称为merge特性的功能,简单来讲,就是 dein 会自动将所有插件plugin/目录都融合merge到一个缓存目录中,目的就是为了减少runtimepath的层级,通常的插件管理器都是将插件的路径添加到runtimepath中,这样runtimepath就会变得很大,插件搜索与加载就会变慢,而 dein 采用merge特性,将所有插件都融合到一个目录中,以后无论安装多少插件,都只需在该目录下进行查找即可,提升了插件加载效率。

    • dein#save_rollback({rollbackfile}[, {plugins}]):保存插件回滚信息到文件{rollbackfile}中。

    • dein#save_state():保存 dein 状态到缓存脚本中。

      dein#save_state()必须在dein#end()后面被调用。
      dein#save_state()会完整保存当前runtimepath,因此在调用后不能再动态更改runtimepath

    • dein#set_hook({plugins}, {hook-name}, {hook}):为插件设置钩子函数{hook},钩子函数名称为{hook-name}

      • {plugins}:如果未指定,则表示为所有插件设置钩子函数。

      dein#set_hook()可以在dein#begin()/dein#end()块后调用。
      dein#set_hook()如果设置在dein#load_state()/dein#save_state()块中的时候,如果钩子函数是函数类型Funcref,那么就不起作用。

      call dein#add('Shougo/neosnippet.vim', {'lazy': 1})
      
      function! Foo() abort
      endfunction
      
      " Does not work for dein#load_state()/dein#save_state() block
      call dein#set_hook('neosnippet.vim', 'hook_source', function('Foo'))
      
      " Does work for dein#load_state()/dein#save_state() block
      call dein#set_hook('neosnippet.vim', 'hook_source', 'echomsg "foo"')
      
    • dein#source([{plugins}]):加载(:source)插件。

      • {plugins}:如果未指定,则会加载所有插件。
    • dein#tap({plugin-name}):如果插件存在且没有被禁止,则返回非 0 数值。

      dein#tap()会初始化全局变量g:dein#name:dein#plugin

    变量

    • g:dein#auto_recache:是否自动调用dein#recache_runtimepath()更新缓存。

      • 1:开启自动更新缓存。
      • 0:则关闭自动更新缓存(默认值)

      :该选项会重新加载$MYVIMRC

    • g:dein#cache_directory:设置缓存目录。

      其默认缓存目录为:dein#begin()指定的路径。

    • g:dein#download_command:默认下载命令。

      其默认值为:curl --silent --location --output
      或者为:wget -q -O
      或者使用 PowerShell。

    • g:dein#enable_name_conversion:使能命名转换。

      • 1:如果值为1,且配置时未指定插件名,则使用dein-options-normalized_name作为插件名称。
      • 0:禁止命名转换(默认值)。
      " 使能命名转换
      let g:dein#enable_name_conversion = 1
      
      if dein#load_state(s:dein_path)
        call dein#begin(s:dein_path)
      
        " 将 asyncrun.vim 名称设置为 asyncrun
        call dein#add('skywind3000/asyncrun.vim',{'normalized_name' :'asyncrun'})
      
        call dein#end()
        call dein#save_state()
      endif
      

      上述代码将插件名为asyncrun.vim修改为asyncrun,现在使用asyncrun可以成功访问插件,使用asyncrun.vim访问会失效。

    • g:dein#enable_notification:开启通知功能。

      • 1:表示开启通知功能。
      • 0:表示失能通知功能(默认值)。

      :该选项涉及外部命令调用,因此在不同的平台上,需要有相应的命令存在,具体为:

    • g:dein#install_max_processes:设置 dein 最大进程数。

      其默认值为 8,即最大开启进程数为 8。

      :如果该值小于等于 1,则表示关闭多进程。

    • g:dein#install_process_timeout:插件安装/更新超时时间,单位为秒。

      其默认值为:120(即超时时间为 120 秒)

    • g:dein#install_progress_type:安装进度条输出样式。

      其值有如下几个选项:

      • 'none':不进行输出
      • 'echo'echo区中显示(默认值)
      • 'tabline'tabline中显示
      • title:标题栏中显示(该选项只在 Neovim 中生效)

      :如果需要在状态栏statusline中进行展示,需要结合dein#get_progress()函数。

    • g:dein#install_message_type:安装消息输出类型。

      其值有如下两个选项:

      • 'none':不输出安装信息
      • 'echo'echo区域显示安装信息
    • g:dein#install_log_filename:安装日志文件。

      该值默认为"",表示失能日志记录。

    • g:dein#name:当前插件名称。

      g:dein#name只能在dein#tap()块中使用。
      g:dein#name已被标记为废弃状态deprecated

    • g:dein#notification_icon:设置通知图标路径。

      该值默认为""

    • g:dein#notification_time:通知显示时长,单位为秒。

      该选项默认值为:2,表示默认显示时间为 2 秒。

      :该选项只支持 Linux 和 Windows 平台。

    • g:dein#plugin:当前插件。

      g:dein#plugin可用在dein#tap()dein-hooks块中。

    • g:dein#types#git#clone_depthgit clone默认历史深度(default history depth)。

      其默认值为 0。
      如果该值设置为 1,则 dein 会采用浅拷贝功能。
      更多信息,请参考:dein-options-type__depth

    • g:dein#types#git#command_pathgit命令路径。

      其默认值为:git

    • g:dein#types#git#default_protocolgit默认使用协议。

      其有两种类型可选:httpsssh
      其默认值为:https

    • g:dein#types#git#pull_commandgit pull命令。

      其默认值为:"pull --ff --ff-only"

    选项(OPTIONS)

    以下是 dein 提供的选项列表简介:dein-options

    • augroup:插件对于VimEnterGUIEnter事件的自动命令组名称。

      类型String

    • build:指定编译脚本。

      类型String

      build指定的命令最终由system()函数执行。
      build会在插件根目录执行命令,如果想使用cd命令,必须结合使用sh -c命令:

      " 在 vimproc.vim 目录下执行 make
      call dein#add('Shougo/vimproc.vim', {'build': 'make'})
      
      " 在 command-t 目录下执行:sh -c "cd ruby/command-t && ruby extconf.rb && make"
      call dein#add('wincent/command-t', {
          \ 'build':'sh -c "cd ruby/command-t && ruby extconf.rb && make"'
          \ })
      
    • depends:指定插件依赖的其他插件。

      类型StringList

      call dein#add('tpope/vim-surround', {
          \'on_map': {'n' : ['cs', 'ds', 'ys'], 'x' : 'S'}, 
          \'depends' : 'vim-repeat'
          \})
      

      depends列表指定的依赖 不会 自动进行安装。
      :对于非懒加载插件,depends指定的依赖插件加载顺序无法确保有序。

    • frozen:如果设置为1,则表示禁止该插件自动更新。

      类型Number

    • ftplugin:这个应该是指定插件类型路径(不是很确定)。

      类型Dictionary,其中:

      • key_时,在加载完所有ftplugin后,会执行该操作。
      • key{filetype}时,就只会加载ftplugin目录中的{filetype}插件。
    • if:添加条件判断。

      类型NumberString,其中:

      • 如果其值为0,则 dein 不会注册该插件,相当于禁止加载插件。
      • 如果其值为String类型,dein 会执行字符串指令。
      • 如果未设置if指令,dein 默认会使能/启用该插件。
    • lazy:设置插件懒加载。

      类型Number,其中:

      • 如果设置为 非0 值,表示启用懒加载(此时 dein 不会把插件路径添加到runtimepath)。
      • 如果未设置lazy选项,dein 会根据插件当前条件自动进行判断是否启用懒加载。

      :对于没有plugin/目录的插件,不要设置懒加载,因为这是没有意义的。可以通过dein#check_lazy_plugins()找到无意义的懒加载插件。

    • merged:启用merged特性。

      类型Number,其中:

      • 如果设置为0,则表示禁止merged特性,这样当前插件的plugin/目录就不会被融合进缓存目录中,这对于插件文件存在冲突的情形下是一个很好的解决方案。
    • name:指定插件名称。

      类型String

      :如果未指定name选项,则 dein 会默认将插件名称设置为插件仓库尾部名称,即:skywind3000/asyncrun.vim的名称为asyncrun.vim
      :插件名称必须全局唯一,如果存在两个或以上相同的插件名称,则后面的会覆盖前面,此时使用name选项自己指定名称就可以很好地解决这个冲突。

    • normalized_name:设置插件标准名称。

      类型String

      :如果未指定normalized_name选项,则默认使用插件名称主体部分作为其标准化名称,如下所示:

      name            : normalized name
      
      denite.nvim       denite
      dein.vim          dein
      vim-quickrun      quickrun
      
    • on_cmd:如果执行了指定的命令,dein 就会加载该插件dein#source()

      类型StringList

      call dein#add('tpope/vim-fugitive', {'on_cmd' : 'Gstatus'})
      

      上述代码中,当我们在 Vim 中执行Gstatus时,dein 就会加载vim-fugitive插件。

    • on_event:当指定的事件发生时,dein 就会加载该插件dein#source()

      类型StringList

      call dein#add('RomainEndelin/vim-projectionist', {
          \    'on_event': ['VimEnter', 'BufRead'],
          \    'on_if': 'findfile(".projections.json", a:event == "VimEnter" ? ";" : ".;") != ""'
          \ })
      
    • on_func:当指定的函数被调用时,dein 就会加载该插件dein#source()

      类型String

      call dein#add('junegunn/fzf', {
          \ 'if': s:has_exec('fzf'),
          \ 'on_cmd': 'FZF',      " 存在 FZF 命令时才加载
          \ 'on_func': 'fzf#run', " 调用了函数 fzf#run 时才进行加载
          \ })
      
    • on_ft:打开指定的文件类型时,才加载插件。

      类型StringList

      call dein#add('bps/vim-textobj-python', { 'on_ft' : 'python' }) 
      call dein#add('tmhedberg/matchit', { 'on_ft' : 'html' })
      
    • on_if:当满足条件时,dein 就会加载该插件dein#source()

      类型String

      on_if选项的默认会在事件BufReadBufNewFileVimEnterFileType发生时进行判断。
      如果存在dein-options-on_event事件,则在dein-options-on_event事件中进行判断,比如:

      call dein#add('blueyed/vim-diminactive',
      \ {'on_event': 'WinEnter', 'on_if': 'winnr("$") > 1'})
      

      上述代码中,on_if会在事件WinEnter发生时进行判断。

    • on_map:当指定模式下,发生指定的按键映射时,加载该插件。

      类型DictionaryListString,其中:

      • 当值为Dictionary类型时,key为模式{mode}指定,其余条目为按键映射:{mapping}[{mapping1},{mapping2},...],比如:
      call dein#add('terryma/vim-multiple-cursors', { 'on_map' : { 'n' : ['<C-n>', '<C-p>'], 'x' : '<C-n>'}})
      
      • 当值为List类型时,则其条目设置格式为:{mapping}[{mode}, {mapping1}, [{mapping2}, ...]],比如:
      call dein#add('dhruvasagar/vim-table-mode', {'on_map'    : '<LocalLeader>t' })
      call dein#add('terryma/vim-multiple-cursors', { 'on_map' : ['<C-n>', '<C-p>']})
      

      :当未指定模式{mode}时,则默认为nx
      on_map选项支持<Plug>按键映射,如果映射只指定了<Plug>,那么实质上映射的是<Plug>(normalized_name,比如:

      " It is same as "'mappings': '<Plug>(anzu'
      call dein#add('osyo-manga/vim-anzu', {'on_map': '<Plug>'})
      
    • on_path:当编辑指定路径的文件时,加载相应插件dein#source()

      类型StringList,其中:

      • 如果值为.*,则表示编辑任何文件时,都加载插件。
      • 其他情况,则只有缓冲区名称匹配on_path指定的字符串时,才进行加载。
      call dein#add('editorconfig/editorconfig-vim', {
          \ 'if': has('pythonx'),
          \ 'on_event': 'InsertEnter',
          \ 'on_path': '.editorconfig',
      \ })
      

      on_path选项对于文件夹浏览类型的插件很有用。

    • on_source:指定插件依赖关系,表示在指定的插件加载后,会加载当前插件。

      类型StringList

      :插件必须设置了懒加载选项。

      " ~/.vim/plugA/plugin/a.vim
      echom 'a.vim loaded!!'
      command! -nargs=0 CmdA :echom 'this is command a'
      echom 'a.vim done!!'
      
      " ~/.vim/plugB/plugin/b.vim
      echom 'b.vim loaded!!'
      command! -nargs=0 CmdB :echom 'this is command b'
      echom 'b.vim done!!'
      
      " ~/.config/nvim/init.vim
      call dein#add('~/.vim/plugA', {
            \ 'on_source': ['plugB'],
            \ 'on_cmd': ['CmdA'],
            \ 'lazy': 1})
      
      call dein#add('~/.vim/plugB', {
            \ 'on_cmd': ['CmdB'],
            \ 'lazy':1 })
      

      上述代码中,当触发加载plugB后,会加载plugA

      官方文档写的是:

      on_source   (List) or (String)
      Load the plugin before the listed plugins are loaded.
      Note: The plugins must be lazy loaded plugins.
      

      on_source指定的插件加载之前,先加载当前插件。
      对应我们上面的例子,应该是当加载plugB之前,先加载plugA
      但是我本地运行显示的结果是:

      • 执行:CmdB,触发加载PlugB,然后再触发加载plugA
      • 执行:CmdA,只触发加载plugAplugB不会被加载。
        因此,我认为官方文档此处存在错误描述。

      :可通过:scriptnames查看已加载的插件(有序)

    • path:指定插件下载路径。

      类型String

    • rev:指定插件版本/标签号。

      类型String,其中:

      • *:如果选项typegit,则表示使用最新的released标签版本
      • 支持通配符选择,比如:0.*
      • 如果typeraw,那么rev必须是一个哈希值。
      call dein#add('Shougo/deol.nvim', { 'rev': 'a1b5108fd5' })
      
    • rtp:将指定目录添加到runtimepath

      类型String

      :当一个仓库中的子目录包含 Vim 插件时,可以通过设置rtp选项将该目录添加到runtimepath中,从而使能插件:

      " 选择仓库 rstacruz/sparkup 的 vim 目录作为插件添加
      call dein#add('rstacruz/sparkup', {'rtp': 'vim'})
      

      :如果rtp为空字符串"",那么 dein 不会将其路径添加到runtimepath

    • script_type:指定脚本类型。

      类型String

      :对于没有按照 Vim 官方文档规定的目录组织结构的插件,可以通过script_type手动设置脚本类型,比如"indent""plugin""ftplugin"...

      call dein#add(
      \ 'https://raw.githubusercontent.com/Shougo/'
      \ . 'shougo-s-github/master/vim/colors/candy.vim',
      \ {'script_type' : 'colors'})
      
      call dein#add(
      \ 'https://github.com/bronzehedwick/impactjs-colorscheme',
      \ {'script_type' : 'colors'})
      
    • timeout:安装/更新插件的超时时间(单位:秒)。

      类型Number

      :如果忽略该选项,那么超时时间由g:dein#install_process_timeout控制。

    • trusted:以管理员权限(sudo)加载插件。

      类型Number,其中:

      • 如果设置为 非0 值,dein 就会使用管理员权限加载插件。
      • 如果未设置,dein 不会进行加载。

      :dein.vim 默认在sudo会话下,不会对插件进行加载,这是为了增加安全性,否则插件在sudo模式下可以进行任何操作。
      但是如果一定需要在sudo会话下加载插件,则为插件添加trusted选项即可。比如,coc.nvim如果没有加载的话,会一直弹出烦人的错误信息(晕),那么最好为其添加trusted选项,避免在sudo会话时一直弹窗:

    call dein#add('neoclide/coc.nvim', {'merged':0, 'rev': 'release', 'trusted': 1})
    

    sudo模式启动后,dein.vim 的状态会变更,导致下一次非sudo会话时,普通插件无法触发加载,此时手动调用call dein#clear_state(),然后重启 Vim 即可。

    • type:指定仓库类型。

      类型String,其值有如下几个可选:

      • none:无仓库
      • raw:原始插件文本(必须指定script_type
      • git:Git 仓库

      :如果忽略该选项,dein 会自动根据{repository}类型设置该选项

    • type__depthgit clone下载历史深度。

      类型Number,其中:

      • 如果忽略该选项,则使用g:dein#types#git#clone_depth
      • 如果该值大于0,则使用浅拷贝,这会加快下载速度。

      :浅拷贝在克隆某些仓库时可能存在问题,具体请参考:

      • https://github.com/Shougo/neobundle.vim/issues/81
      • https://github.com/Homebrew/homebrew/issues/12024

      :建议不使用浅拷贝机制,反正时间不会增加多少。

    钩子函数(HOOKS)

    dein 提供了一些钩子函数,对于插件的初始化操作很有用。

    :函数类型的钩子函数( Function hooks)不会被缓存,必须手动初始化。
    :对于非懒加载插件,钩子函数的加载顺序无法保证有序。
    :钩子函数的字符串表达式以命令行模式(Ex commands)进行执行。
    :钩子函数中涉及多个操作时,使用换行符进行分割。

    以下是 dein 提供的钩子函数简介:

    • hook_add:当解析完dein#add()行后,触发该钩子函数。

      类型StringFunction

      cal dein#add("~/.vim/plugA", {
          \'hook_add': "echom 'hook_add invoked!!'"
          \})
      

      上述代码为本地插件plugA设置了一个hook_add钩子,当 dein 解析到call dein#add("~/.vim/plugA")语句后,会先调用钩子函数hoot_add,然后再加载插件plugA

      当钩子函数涉及多个操作时,使用换行符进行分割,如下所示:

      call dein#add('kana/vim-niceblock', {
          \ 'hook_add': join(['xmap I  <Plug>(niceblock-I)',
                              'xmap A  <Plug>(niceblock-A)'], "\n")
          \ })
      call dein#add('godlygeek/csapprox', {
          \ 'hook_add': "
          \ let g:CSApprox_konsole = 1\n
          \ let g:CSApprox_attr_map =
          \     { 'bold' : 'bold', 'italic' : '', 'sp' : '' }\n
          \ "})
      

      :不能在钩子函数hook_add中调用插件内定义的函数,因此此时插件还未加载。

    • hook_done_update:当所有插件都更新完毕后,触发该钩子函数。

      类型StringFunction

    • hook_post_source:当插件加载(:source)完成后,触发该钩子函数。

      类型StringFunction

      cal dein#add("~/.vim/plugA", {
          \'lazy': 1,
          \'on_cmd': ['CmdA'],
          \'hook_post_source': "echom 'hook_post_source invoked!!'"
          \})
      

      :本人实验过后,发现hook_post_source只在懒加载插件上才会被回调,如果要想让插件每次加载(无论是懒加载还是直接加载)时,都能触发hook_post_source,则可以VimEnter事件手动触发:

      autocmd VimEnter * call dein#call_hook('post_source')
      
    • hook_post_update:当插件更新完成后,触发该钩子函数。

      类型StringFunction

    • hook_source:在加载(:source)插件前,触发该钩子函数。

      类型StringFunction

      hoot_sourcehook_post_source一致,只能作用于栏加载插件,如果要想让插件每次加载(无论是懒加载还是直接加载)时,都能触发hook_source,则必须手动进行触发:

      call dein#begin()
      ...
      call dein#end()
      call dein#call_hook('source')
      

      hook_source不能跟hoo_post_source一样,结合VimEnter使用,因为插件直接加载发生在VimEnter事件之前,如果hook_sourceVimEnter结合,实际上是等到插件加载完成后,才会触发hook_source,此时该钩子的作用就与hook_post_source一样了。

    参考

    相关文章

      网友评论

        本文标题:Vim 插件管理器 - dein.vim

        本文链接:https://www.haomeiwen.com/subject/einszhtx.html