Full Vim: Plugin manager without fatal flaws
Table of contents
- Introduction (vim_lib)
- Plugin manager without fatal flaws (vim_lib, vim_plugmanager)
- Project level and file system (vim_prj, nerdtree)
- Snippets and file templates (UltiSnips, vim_template)
- Compiling and executing anything (vim-quickrun)
- Work with Git (vim_git)
- Deploy (vim_deploy)
- Testing with xUnit (vim_unittest)
- The library on which everything rests (vim_lib)
- Other useful plugins
I probably used all the popular plugin managers for Vim and I didn’t have the slightest desire to write my own, as these completely suited me, but there was a small one, which I will discuss in this article.
Bad Other Managers
How does the plugin manager for Vim work? Everything is trivial. At the start of the editor, .vimrc is read in which all the currently used plugins are declared. These names are concatenated with the address of the directory that the plugins should be stored and the resulting lines are added to runtimepath - the Vim variable, which determines where the editor gets start scripts, plugins, and everything else.
The main problem with most popular Vim plugin managers is that they populate the runtimepath variableanyhow. What does this lead to? Plugins are loaded randomly, there is no way to override the plugin settings for a specific project, plugins override your own Vim settings, etc. It is even more aggravated by the inability to control the order of loading plug-ins, when you need to first download plug-in A, and only then the goodies B dependent on it. In a word - pain.
What we need ideally
I have already said before and I will dwell on this issue in more detail in the next article, but now I will only touch on it a little. The structure I propose adds another level of initialization to the Vim editor. This means that your Vim configurations and plugins will exist on three levels:
- System ( $ VIMRUNTIME / ) - configurations and plugins that apply to all users of the system
- User ( ~ / .vim / ) - configurations and plugins of a specific user
- Project ( ./.vim/ ) - configurations and plugins available only in this project. It is this level that Vim does not have, or rather it exists, but it is implemented rather poorly
This will allow, for example, customizing templates for Java classes, and then overriding them for a specific project. You can also install some plugin only for a specific project, and this plugin will not be loaded by Vim in other projects, which will save memory and increase editor productivity (for example, you decide to start working with Lua and do not want to put plugins in ~ / .vim / ). Just imagine, one editor for all occasions and no lags.
Plugin standards
The vim_lib library defines both the structure of Vim plug-ins (but does not limit you to this structure only, any plug-in can be used) and the order in which they are connected and loaded, for this, the sys / Plugin and sys / Autoload classes are implemented, respectively.
If we implement the plugin in strict accordance with the requirements of the sys / Plugin class , then we get the following structure:
myPlugin/
plugin/
myPlugin.vim
autoload/
...
myPlugin.vim
doc/
myPlugin.rux
The plugin / myPlugin.vim file contains the plugin initialization and connection logic.
Example
" Date Create: 2015-02-23 22:45:56
" Last Change: 2015-06-07 18:21:15
" Author: Artur Sh. Mamedbekov (Artur-Mamedbekov@yandex.ru)
" License: GNU GPL v3 (http://www.gnu.org/copyleft/gpl.html)
" Аналог use в VimLanguage
let s:Plugin = vim_lib#sys#Plugin#
let s:System = vim_lib#sys#System#.new()
let s:p = s:Plugin.new('vim_write', '1') " Создание объекта плагина с указанием его имени и версии
" Опции плагина
"" {{{
" @var bool Следует ли выполнять замену ключевых значений в файле перед сохранением.
"" }}}
let s:p.preplace = 1
"" {{{
" @var bool Включен ли механизм автосохранения изменений.
"" }}}
let s:p.aw = 0
"" {{{
" @var string|array Массив, содержащий имена типов файлов, для которых задействован механизм автосохранения изменений. Если опция установлена в значение 'all', механизм задействован для всех типов файлов.
"" }}}
let s:p.awTypes = 'all'
if !exists('g:vim_write#replacement')
"" {{{
" @var hash Словарь замен, используемый перед записью буфера для замены ключевых слов. Словарь имеет следующую структуру: {типФайла: [regexp, ...]}. Тип 'all' используется для всех файлов.
"" }}}
let g:vim_write#replacement = {}
endif
" Функция инициализации плагина, в ней можно писать любую логику
function! s:p.run() " {{{
call s:System.au('BufWritePre,FileWritePre', function('vim_write#_writePre'))
call s:System.au('CursorHold', function('vim_write#_autowrite'))
endfunction " }}}
" Объявление пунктов меню плагина. Они попадут в Plugins.имяПлагина.пунктМеню
call s:p.menu('Aw_start', 'awstart', '1')
call s:p.menu('Aw_stop', 'awstop', '2')
" Объявление команд плагина
call s:p.comm('VimWriteAwStart', 'awstart()')
call s:p.comm('VimWriteAwStop', 'awstop()')
call s:p.reg() " Регистрация плагина, которая делает его доступным в редакторе
The autoload / myPlugin.vim file contains plugin methods. Experienced Vim users will immediately notice that the main code of the plugin will be loaded the first time it is used, and not during the launch of the editor. This is done through a global call to the plugin methods. For example, when executing the VimWriteAwStart command from the previous example, the Plug-in name method # awstart () will be called .
Example
" Date Create: 2015-02-23 22:48:37
" Last Change: 2015-06-07 18:21:15
" Author: Artur Sh. Mamedbekov (Artur-Mamedbekov@yandex.ru)
" License: GNU GPL v3 (http://www.gnu.org/copyleft/gpl.html)
" Аналог use в VimLanguage
let s:Publisher = vim_lib#sys#Publisher#.new()
let s:Content = vim_lib#sys#Content#.new()
"" {{{
" Метод активирует механизм автосохранение.
"" }}}
function! vim_write#awstart() " {{{
let g:vim_write#.autowrite = 1
endfunction " }}}
...
The doc / myPlugin.rux file contains the documentation for the plugin.
Why is all this necessary? First is standardization. Writing, modifying, and understanding plugins becomes easier. Secondly, they are easier to disable.
Read more here .
Autoload
The sys / Authoload class of the library defines the initialization order of both the Vim editor and its plugins. Initialization is carried out in several stages:
- Connection of the main editor configuration files ( $ VIMRUNTIME )
- Connecting system-wide plugins ( $ VIMRUNTIME / plugin / )
- Connection of file-dependent configurations ( $ VIMRUNTIME / ftplugin / )
- Connecting basic user configuration files ( ~ / .vimrc )
- Connecting custom plugins ( ~ / .vim / plugin / )
- Connecting file-dependent user plugins ( ~ / .vim / ftplugin / )
- Connecting the main project configuration files ( ./.vimrc )
- Connecting project plugins ( ./.vim/plugin/ )
- Connection of file-dependent project plugins ( ./.vim/ftplugin )
This is done using the familiar runtimepath variable , but the order of loading plugins, their localization (system, user or project) is taken into account, and the mechanism for redefining the configurations of both the editor and any plug-ins at each level is supported (the project level is the highest priority) .
In general, the sys / Authoload class allows you to implement any nesting hierarchy and configuration priority, not just a three-step one, but I did not see the need to add new levels.
To use the autoload offered by the sys / Authoload class , just add the following lines to your .vimrc file :
filetype off
set rtp=~/.vim/bundle/vim_lib
call vim_lib#sys#Autoload#init('~/.vim', 'bundle') " Адрес до вашего ~/.vim/bundle
Plugin 'vim_lib'
" Другие плагины
filetype indent plugin on
This can be done not only at the user level ( ~ / .vimrc ), but also at the system level ( $ VIMRUNTIME / .vimrc ) or project ( ./.vimrc ), while the startup logic will be distributed only from this level and “below”. At all the lower levels, it’s enough to simply connect new plugins that are available only to this level:
filetype off
call vim_lib#sys#Autoload#init('.vim', 'bundle') " Подключение плагина на проектном уровне
Plugin 'myPlugin'
filetype indent plugin on
To disable the plugin, just comment out the Plugin 'name' line .
You can configure the plugin directly during its connection:
Plugin 'vim_deploy', {
\ 'options': {'adapter': 'shipit'}, " Переопределение опций плагина
\ 'map': {'deploy': 'd'}, " Переопределение горячих клавиш
\}
At lower levels, you can override these configurations:
let g:vim_deploy#options = {'adapter': 'gradle'}
Everything is very flexible and convenient.
Plugin Manager
It would seem that it makes it difficult to force other plugin managers to install plugins in the directories we need (system, user or project)? The problem here is that other managers do not just install third-party plugins, but also determine the order from the initialization, and we don’t need it (already implemented by the sys / Authoload class of the library). The same Vim plugin incompatibility problem that I talked about in a previous article. I had to write my decision.
vim_plugmanager has a fairly simple interface and allows you to install plugins from GitHub into the system directory, user directory or project directory, depending on where you are right now.
Plugin listing window

As you can see in the figure, vim_plugmanager is implemented as a window in which it displays a list of currently installed plugins (namely installed, not connected) with grouping by level. To add a new plugin, just press the a key , and to delete, move the cursor to the plugin and press dd (very familiar, right?).
After installing a new plugin, you must connect it. To do this, as mentioned above, it is enough to add to the current .vimrc (current level) Plugin record 'Plugin name' . This is necessary because the installation of the plugin is copying it to the directory with the plugins, and the connection adds it to vimruntimeafter which it can be loaded by the editor.
Read more here .
Bye bye
In this article, I have covered far from all the problems that I encountered when using Vim plugins, as well as not all the possibilities of the solutions described. I don’t think it’s worth copying the documentation when it’s publicly available.
Perhaps I could get by with the existing solutions, crossing them between each other, but in this case there was a risk to spend much more time, and as a result get not what I needed.
Only registered users can participate in the survey. Please come in.
Does the Vim plug-in manager need an automatic dependency resolution function (implemented)
- 93.5% Yes 29
- 3.2% No 1
- 3.2% Other (I will answer in the comments) 1