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 doing anything (vim-quickrun)
- Work with Git (vim_git)
- Deploy (vim_deploy)
- Testing with xUnit (vim_unittest)
- The library on which everything is kept (vim_lib)
- Other useful plugins
Is it worth telling you how code and design reuse makes the programmer's life easier? But can we reuse everything? Very often in my projects I encounter tasks that require copy-paste code and this cannot be avoided. The category of this “repeatable” code includes all structures of the used PL, many project classes and test cases. Fortunately, a solution has long been invented that allows you to work with such code faster and better.
Duplicate Code Levels
Inevitably repetitive code can be divided by scale into two groups:
- Structures of PL or code blocks - for example, structures for, if / else, while, class, as well as ready-made solutions that can not be copied and pasted
- Entire files — for example, unit test files, documentation, entity classes
For each group, different solutions are used, allowing copy-paste code quickly and easily. Naturally, these solutions are already implemented in the Vim editor, and I suggest trying them.
Snippets
Snippets are named snippets of code (yes, anything), which can be quickly inserted by typing the name of the snippet and pressing the “hot key”. For example, you want to insert the getter method into the class, which returns the
login property. Using snippets, you only need to type the word
get in the place where the method will be located, and then press the
Tab key. As a result, the getter template of the method will be inserted, and the pointer will be placed in the body of the method so that you can specify the name of the returned property.
Examplepublic function get(){ return $this->_; }
Take a look at an example. The pointer will be placed in place of the underscore character (_). After entering the word
login , the name of the method will be changed automatically.
Example public function getLogin(){ return $this->login; }
Convenient, isn't it? But the
UltiSnips plugin allows
you to implement templates for tasks of any complexity, whether they are language structures or whole classes. I have been using this plugin for quite some time to implement snippets in Vim.
For example, in one of my projects in which high security is important, I use secure programming. For this project, I implemented several snippets that allow you to quickly check the input parameters of methods. So, typing
assertpositive, I get a view template:
assert('is_int(_) && _ > 0');
That is, checking the input parameter to belong to the type
int and value is greater than zero.
')
Another example are my snippets for Habr. Did you know that using the plugin for Firefox, which is called
Vimperator , you can write articles on Habr directly from Vim? To do this, simply open the article editing window and place the pointer in the textarea and press the
Ctrl + i combination. After that, the Vim editor will open and everything you write in it after saving (
: wq ) will be copied to this textarea. Cool? And how about using snippets to insert html tags? So, to add habracut, just type
cut and press
Tab , and you will get a ready-made tag. You can say that snippets are already implemented directly in the menu:

But you are using Vim, which means that a computer mouse is the number one enemy for you!
You will love snippets, if you have to write in different PL. In this case, you do not have to memorize exactly how certain structures are written in a particular language, but it is enough to implement snippets with similar names. For example, I always forget how certain structures are implemented on Bash, because I just use such snippets as
if ,
for ,
foreach , etc.
I do not want to describe in this article how to write snippets for UltiSnips, since the official documentation will make it much better than me, I will give only a small example of a snippet declaration for creating a getter method:
Example snippet get "public function get ..." b /** * $2. * @return ${3:mixed} */ public function get${1/\w+\s*/\u$0/}(){ return $this->$1; }$0 endsnippet
Templates
Once I paid attention to how much time I have to spend on creating documentation for my Vim plugins. The fact is that the documentation files have a certain structure:
Example .txt Vim 7.0. ` ` 1. -description 2. -requirements 3. -install 4. -use 5. -opt 6. -commands 7. -menu 8. -events ================================================================================ 1. -description ... ================================================================================ 2. -requirements Vim 7.0 . vim_lib https://github.com/Bashka/vim_lib vim_lib
Typically, the Vim plugin documentation includes about a hundred lines, of which about sixty are template data, such as a header, table of contents, and sections. Using snippets to create documentation would require repetitive actions from me, which I did not want. Then I decided to write a
vim_template plugin. This plugin fills an empty file with some data, creating a template and depriving me of having to repeat operations of the same type to prepare the file for work. File templates can be configured very flexibly using VimLanguage, which allows you to create files with a very complex structure (for example, automatically add a namespace to the beginning of the file, taking into account the class location in the file system). Another feature of the plugin is the ability to determine the context of the template. For example, you can create a template only for test case files or for files located in the
~ / .vim / bundle / directory, and loading the project level, which I have already mentioned in previous articles, allows you to define templates only for a specific project.
The vim_template plugin is pretty simple. When you open a file, it sequentially searches for a template file (in the directories
./.vim/templates ,
~ / .vim / templates and
$ VIMRUNTIME / templates ), the contents of which will be compiled and inserted into this file. The search logic of the template file allows not only to start from the file name, but also to take into account its location in the file system. Here are some examples:
- If there is a ___. Php template, then it will be applied to all files with this extension.
- If there is a template ___ Test.php, then it will be applied to all test cases for PHP classes, overlapping the previous
- If there is an autoload / ___. Vim template, then it will be applied to all files with the vim extension, which are located in the autoload directory
- If the template is located belongs to the project (located in the ./.vim/templates directory), then it will be used only in this project.
Convenient and flexible, isn't it? Here are some examples from real projects:
- Vim plugin documentation templates
- Templates for Vim plugin files located in the plugin and autoload directory (they usually have similar structures)
- Templates for test cases
- Templates for Entities and Mappers
As already mentioned, the contents of the templates are not simply copied into the new file, but are precompiled, so that you can insert data into the new file that can be obtained only during the insertion of the template, for example:
- Information about the author, license, creation date
- Class name derived from file name
- class namespace, obtained from the file system location
- A constant whose value is calculated based on the file name or location in the file system
All this is done with the help of special markers, which are replaced with the values during the template insertion (they are inserted into the template as the following
<<name +> ). These markers may be listed in the
vim_template # keywords and
vim_prj # opt dictionaries. Personally, I use such markers as: author, email, license, etc. In addition to the markers listed by you, predefined ones are also available:
- date - current date
- time - current time
- datetime - date and time
- file - the name of the current file
- ftype - the extension of the current file
- fname - the name of the current file without the extension
- dir - address of the directory in which the current file is located, relative to the project root
- namespace - the address of the current file relative to the project root
But on the predefined markers you will not get far, therefore the use of "executable markers" is possible (they are enclosed in slanting quotes). These are the VimLanguage code blocks that will be executed when the template is inserted. With their help, you can convert markers (for example, turn the
dir marker into the namespace of the current class by replacing the slash with a dot), calculate new markers, etc. All standard markers are available here as local variables Vim (
l: date ,
l: dir ,
l: file, etc.).
As an example, I’ll give a template for the Mapper class used in my current project:
Example <?php class `substitute(strpart(l:dir, strlen('application/')), '/', '_', 'g')`_<+fname+> extends My_Db_Mapper{ public function getDefaultTable(){ $tableName = '`tolower(substitute(strpart(l:dir, strlen("application/db/")), "/", "_", "g") . "_" . strpart(l:fname, 0, strlen(l:fname) - strlen("Mapper")))`'; $table = new My_Db_Table([ 'name' => $tableName, ]); $table->_linkedCacheTags = [$tableName]; return $table; } protected function getStateEntity(\My_Db_Entity $entity){ return [ '' => $entity->(), ]; } protected function setStateEntity(array $state, \My_Db_Entity $entity){ $entity->($state['']); } protected function getEmptyEntity(){ return new `substitute(strpart(l:dir, strlen('application/')), '/', '_', 'g')`_`strpart(l:fname, 0, strlen(l:fname) - strlen('Mapper'))`; } }
When creating a new file, for example
ClientMapper.php , the plugin fills it as follows:
Example <?php class Db_ClientMapper extends My_Db_Mapper{ public function getDefaultTable(){ $tableName = '_client'; $table = new My_Db_Table([ 'name' => $tableName, ]); $table->_linkedCacheTags = [$tableName]; return $table; } protected function getStateEntity(\My_Db_Entity $entity){ return [ '' => $entity->(), ]; } protected function setStateEntity(array $state, \My_Db_Entity $entity){ $entity->($state['']); } protected function getEmptyEntity(){ return new Db_Client; } }
Note that the namespace for the class is calculated automatically. All that remains is to add a little private solutions to the class and it is ready to go.
Bye all
If you have to repeat the same structure while working with Vim, try implementing a suitable snippet or a template file, it will save you a lot of time. Of course, you will have to learn VimLanguage and the snippets writing language, but it will more than pay off when you start creating entire projects in a few hours.