If you have used Sublime Text before, you may be familiar with the snippet function. Snippets let you input a trigger word and expand the trigger to some boilerplate code or string you do not want to repeat each time. You will increase your efficiency dramatically with the help of snippets.

There are several snippet plugins available: snipmate, neosnippet and ultisnips etc. All these plugins are good enough for simple use cases. If you donot know which one to use, just try ultisnips. In this post, I would like to share how to configure ultisnips and how to use your own snippets in Neovim.

Install

In fact, ultisnips is just a snippet engine. To use the real snippets, you also need to install vim-snippets, which provides a comprehensive list of snippets for various filetypes. You can install the two plugins with your favorite plugin manager.

Ultisnips integrates automatically with the auto-completion engine deoplete. If you have installed deoplete, you will see the auto-completion menu for your snippet keywords without any settings.

The minimum settings for ultisnips are:

" Trigger configuration. Do not use <tab> if you use
" https://github.com/Valloric/YouCompleteMe.
let g:UltiSnipsExpandTrigger='<tab>'

" shortcut to go to next position
let g:UltiSnipsJumpForwardTrigger='<c-j>'

" shortcut to go to previous position
let g:UltiSnipsJumpBackwardTrigger='<c-k>'

In the above setting, we set the trigger key to Tab, i.e., after typing the keyword for a snippet, you then press Tab to trigger snippet expansion. You may define several positions (these positions may optionally contains placeholder texts) in your snippet. In the above settings, Ctrl-J and Ctrl-K is used to jump forward and backward in these positions.

How to use

All the snippets provided by vim-snippets can be found here. The snippet file for filetype FOO has name FOO.snippets, e.g., for python, the snippet file is python.snippets. Filetype snippets are only available for the specific file types. There is also a all.snippets file which means that snippets inside this file are available for all file types.

A snippet looks like the following:

snippet KEYWORD "some description"

snippet body...

endsnippet

, where KEYWORD is the trigger for the snippet. If you type KEYWORD and press the trigger key, it will be expanded to the snippet content.

For example, there is a date keyword in all.snippets, if you type date, you will see an auto-completion item for it. If you press Tab and it will be expanded to current date.

Use your own snippets

It is easy to write a simple snippet. For example, to create a kbd tag quickly when writing Markdown files, we can create a snippet for it. Here is how to do it.

First, create a file named markdown.snippets and add the following content:

snippet kbd "HTML kbd tag"
<kbd>$1</kbd>
endsnippet

This will create a snippet named kbd for filetype markdown.

Where to store my custom snippets?

After creating the snippet files, we should put it in a directory where ultisnips can find them. This issue is a little tricky for Neovim.

The documentation of UltiSnips has explained how the snippet files are searched (see :h UltiSnips-how-snippets-are-loaded). But it is still not crystal clear how to configure so that our custom snippets can be found by UltiSnips.

From the documentation of UltiSnips:

UltiSnips will search each ‘runtimepath’ directory for the subdirectory names defined in g:UltiSnipsSnippetDirectories in the order they are defined. For example, if you keep your snippets in ~/.vim/mycoolsnippetsand you want to make use of the UltiSnips snippets that come with other plugins, add the following to your vimrc file.

let g:UltiSnipsSnippetDirectories=[“UltiSnips”, “mycoolsnippets”]

The description above is both informative and confusing because it is written for Vim users, not Neovim users. As a result, if you follow the above example, you will find that your custom snippets are not available for auto-completion.

In the following, I will summarize what is working for Neovim.

First, open nvim and use the command :echo &runtimepath. This command will print all the runtime paths that Neovim will search. According to the documentaion, your custom snippets directory should be put under one of these runtime paths. On my Windows machine, the output is like (the full output is omitted for brevity):

C:\Users\Administrator\AppData\Local\nvim,C:\Users\Administrator\AppData\Local\nvim\plugged\deoplete.nvim,C:\Users\Administrator\AppData\Local\nvim\plugged\deoplete-jedi,C:\Users\Administrator\AppData\Local\nvim\plugged\neco-vim,…..

On my Linux machine, the output is like (the full output is omitted):

/home/jdhao/.config/nvim,/home/jdhao/.local/share/nvim/plugged/deoplete.nvim/,/home/jdhao/.local/share/nvim/plugged/deoplete-jedi/,/home/jdhao/.local/share/nvim/plugged/jedi-vim/,…..

Different runtime paths are separated by a comma. The steps of configuring custom snippets are the same for both Windows and Linux. So in the following part, I will only focus on Linux since it is more popular.

One of the runtime paths on Linux is /home/jdhao/.config/nvim. We choose this directory and create a folder named my_snippets under it. Then move the markdown.snippets file you have just created into this folder.

In the third step, we add the following setting to init.vim:

" `my_snippets` is the directory we created before
let g:UltiSnipsSnippetDirectories=["UltiSnips", "my_snippets"]

Now, open a Markdown file and start typing kbd and you should be able to see the kbd auto-complete item:

The completion engine I am using is deoplete and US means that this completion item is from UltiSnips.

References