📜 ⬆️ ⬇️

Vim in full: Plugin Manager without fatal flaws

Table of contents


  1. Introduction (vim_lib)
  2. Plugin Manager without fatal flaws (vim_lib, vim_plugmanager)
  3. Project level and file system (vim_prj, nerdtree)
  4. Snippets and File Templates (UltiSnips, vim_template)
  5. Compiling and doing anything (vim-quickrun)
  6. Work with Git (vim_git)
  7. Deploy (vim_deploy)
  8. Testing with xUnit (vim_unittest)
  9. The library on which everything is kept (vim_lib)
  10. 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 were fine with me, but it was a little but about which I will cover in this article.


Bad Other Managers


How does the plugin manager for Vim work? Everything is trivial. During the start of the editor, the .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 store and the resulting lines are added to the runtimepath - the Vim variable, which determines where the editor gets the start scripts, plugins and everything else.

The main problem with most popular plugin managers for Vim is that they populate the runtimepath variable as they like. What does this lead to? The plugins are loaded randomly, there is no possibility to override the plugin settings for a specific project, the 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 first need to load plug-in A, and only then the blessing dependent on it B. In a word, pain.
')

What we need ideally


I have already spoken before and will dwell on this issue in more detail in the next article, and now I will only touch it a little. The structure proposed by me adds another level of initialization of the Vim editor. This means that your Vim configurations and plugins will exist on three levels:
  1. System ( $ VIMRUNTIME / ) - configurations and plugins that apply to all users of the system
  2. User ( ~ / .vim / ) - configurations and plugins for a specific user
  3. Project ( ./.vim/ ) - configurations and plugins available only in this project. This level is not in Vim, or rather, it is, but it is implemented rather weakly.

This will allow, for example, to customize templates for Java classes and then redefine them for a particular project. You can also install some plugin only for a specific project, and this plugin will not load Vim in other projects, which will save memory and increase editor's performance (for example, you decided to start working with Lua and do not want to install plugins in ~ / .vim / ). Just imagine, one editor for all occasions and no lags.

Plug-in Standards


The vim_lib library defines both the structure of Vim plug-ins (but does not limit you to just this structure, 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, we will get the following structure:
myPlugin/ plugin/ myPlugin.vim autoload/ ... myPlugin.vim doc/ myPlugin.rux 

The plugin / myPlugin.vim file contains the logic for initializing and connecting the plugin.
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 users of Vim will immediately notice that the main code of the plug-in will be loaded when it is first used, and not during the launch of the editor. This is done through a global call to plugin methods. For example, when executing the VimWriteAwStart command from the previous example, the Plugin 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 plugin documentation.

Why is all this necessary? First, standardization. Writing, changing and understanding plugins is easier. Secondly, it's easier to turn them off.

You can read more here .

Autoload


The library sys / Authoload class defines the initialization order of both the Vim editor itself and its plug-ins. Initialization is performed in several stages:
  1. Connecting the main editor configuration files ( $ VIMRUNTIME )
  2. Connecting system-wide plugins ( $ VIMRUNTIME / plugin / )
  3. Connecting file-dependent configurations ( $ VIMRUNTIME / ftplugin / )
  4. Connecting the main user configuration files ( ~ / .vimrc )
  5. Connecting custom plugins ( ~ / .vim / plugin / )
  6. Connecting user-specific plug-ins ( ~ / .vim / ftplugin / )
  7. Connecting the main project configuration files ( ./.vimrc )
  8. Connecting project plugins ( ./.vim/plugin/ )
  9. Connecting file-dependent project plugins ( ./.vim/ftplugin )

This is done using the runtimepath variable already familiar to us, but the order of loading plugins, their localization (system, user or project) is taken into account, and the mechanism for overriding configurations of both the editor and any plug-ins at each level is supported (the design level is the highest priority) .

In general, the sys / Authoload class allows you to implement any hierarchy of nesting and priority configurations, not just a three-step, 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 level ( ./.vimrc ), while the startup logic will be distributed only from this level and “below”. At all lower levels it is enough just to connect new plugins 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, simply comment out the line Plugin 'name' .

You can configure the plugin directly during its connection:
 Plugin 'vim_deploy', { \ 'options': {'adapter': 'shipit'}, "    \ 'map': {'deploy': '<Leader>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 what prevents other plug-in managers from installing plug-ins in the directories we need (system, user, or project)? The problem here is that other managers do not just install third-party plug-ins, but also determine the order from initialization, but we don’t need it (already implemented by the library sys / Authoload class). The same incompatibility problem Vim plug-ins, which I mentioned in the 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 currently.
Plugin list window


As can be seen in the figure, vim_plugmanager is implemented as a window in which it displays a list of currently installed plug-ins (installed and not connected) grouped by levels. To add a new plug-in, just press the a key, and to delete, move the cursor over the plug-in and press dd (very familiar, isn't it?).

After installing a new plug-in, you must connect it. For this, as mentioned above, it is enough to add to the current .vimrc (current level) Plugin entry 'Plugin name' . This is necessary because the installation of the plug-in is copying it to the directory with plug-ins, and the connection adds it to vimruntime , after which it can be loaded by the editor.

You can read more here .

Bye all


In this article, I have highlighted far from all the problems I encountered when using Vim plugins, as well as not all the features of the described solutions. I don’t think it's worth copying the documentation when it is publicly available.

Perhaps I could get by with the existing solutions, crossing them among themselves, but in this case there was a risk of spending much more time, and as a result I didn’t get what I needed.

Source: https://habr.com/ru/post/259725/


All Articles