Snippets are small fragments of reusable code which, in all the major text editors, can be defined, organized and associated to key shortcuts. Although in Vim it is possible to create snippets without using any plugin, Ultisnips provide us extra features and write snippets using a clean and well documented syntax.
In this article we learn how to install the Ultisnips plugin and how to use it to write and manage snippets in Vim.
In this tutorial you will learn:
- How to install the Ultisnips plugin and some predefined snippets
- How to use Ultisnips
- How to create custom snippets

Category | Requirements, Conventions or Software Version Used |
---|---|
System | Distribution agnostic |
Software | Vim >= 8 |
Other | Privileged access to your Linux system as root or via the sudo command in order to perform system-wide installation of required packages |
Conventions | # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux-commands to be executed as a regular non-privileged user |
Installing Ultisnips
There are various ways to install Ultisnips, or any Vim plugin, in general. We can use the Vim native package system, a traditional plugin loader like Pathogen, or a proper plugin manager like Plug. Let’s briefly explore these options.
Installing Ultisnips using Vim native package system
Recent versions of Vim (>= 8) are able to load and organize plugins without using external plugin managers, thanks to the native package system. To install a plugin using this method, we have to create the following directory tree under ~/.vim
:
$ mkdir -p ~/.vim/pack/plugins/{start,opt}
In the example above “plugins” is an arbitrary name for a directory under
~/.vim/pack
, containing two sub-directories: start
and opt
. Plugins we install under the former are loaded automatically, those we install under the latter, are loaded on demand. Here we install the Ultisnips plugin using the first strategy:
$ git clone https://github.com/SirVer/ultisnips ~/.vim/pack/plugins/start/ultisnips
Installing Ultisnips using Pathogen
In older Vim versions, functionalities similar to those provided by the native package system, could be obtained using the Pathogen plugin. Pathogen let us install each plugin in its own directory by modifying the Vim runtime path. To install Pathogen, which is itself a plugin, we can execute the following commands:
$ mkdir -p ~/.vim/{autoload,bundle} $ curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
The command creates the “autoload” and “bundle” directories under ~/.vim
. The former is a native Vim directory: the editor automatically loads scripts contained in it. That’s where we downloaded Pathogen. The latter is the directory where Pathogen looks for plugins, and where we must clone the Ultisnips repository:
$ git clone https://github.com/SirVer/ultisnips ~/.vim/bundle/ultisnips
In order for Pathogen to work, we need to add this code to our ~/.vimrc
file:
execute pathogen#infect()
Installing Ultisnips using Plug
Plugin installation methods we used in the previous examples are really simple. Both Pathogen and the Vim native system are not “proper” plugin managers: they just let us organize and load plugins in a clean way. If we are looking for more advanced features we must use a proper plugin manager: one of the most used is Plug. This plugins manager has the ability to install, update and remove plugins by itself; it lets us associate the loading of plugins to specific file types, and execute post-installation functions.
To install Plug automatically the first time we open Vim, we can add the following code to
~/.vimrc
:
if empty(glob('~/.vim/autoload/plug.vim')) silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim endif
We list the plugins we want to install between the plug#begin()
and plug#end()
function calls. In this case, to install Ultisnips, we write:
plug#begin() Plug 'SirVer/ultisnips' plug#end()
To actually install the plugin we run:
:PlugInstall
Installing pre-made snippets
Utilsnips provides only the snippet engine. A vast collection of snippets is maintained in a separate repository. We can install it as if it was just another plugin, using one of the methods we saw before. Using Plug, for example, we would just add the repository to the list:
plug#begin() Plug 'SirVer/ultisnips' Plug 'honza/vim-snippets' plug#end()
Snippets are organized by language. All HTML snippets, for example, can be found in the html.snippets file.
Using snippets
We have some snippets available, let’s see how to use them. One of the available HTML snippets allows us to quickly create a hyperlink. Here is the snippet code:
snippet a "Link" w <a href="${1:http://www.${2:url.com}}"${3: target="_blank"}>${4:Anchor Text}</a> endsnippet
We define Utilsnips snippets between “snippet” and “endsnippet” instructions, using the following syntax:
snippet <trigger> [<snippet-name> [<options>] ]
Where “trigger” is the text which triggers the expansion, and “snippet-name” is a string used for reference. Finally, “options” are a series of options which defines the snippet behavior (See
:help UltiSnips-snippet-options
). Both “snippet-name” and “options” can be omitted.
Inside the snippet definition we can see numeric tabstops:
${2:url.com}
Those are very useful since represent places where the cursor automatically moves to when the snippet expands, and when we press the “JumpForward” (Ctrl+j) and “JumpBackward” triggers (Ctrl+k). The value you see after “:” is the tabstop default text. Let’s see the snippet in action:

First of all we pressed i
to enter “insert” mode, then we wrote “a” (think of the <a>
tag) and pressed <tab>
, which is the default “ExpandTrigger” key. As you can see in the video, the snippet expanded, and the cursor moved on the “$1” tabstop.
In the snippet we are using as an example, the “$2” tabstop is “nested” inside the first one. To navigate forward to it, we pressed Ctrl+j (the “JumpForwardTrigger”): the value of the second tabstop was selected (the “url.com” part), and we replaced it with “linuxconfig.org”.
By pressing Ctrl+j again, we moved to the third tabstop, then again to the fourth one which corresponds to the link anchor, which we modified. See how powerful the Ultisnips plugin can be? We can even define our own snippets, let’s see how.
Creating custom snippets
Custom snippets can be defined in the ~/.vim/UltiSnips
directory (see :help UltiSnipsSnippetDirectories
). Suppose we want to define a custom HTML snippet to automatically generate the tags required to work with the Prism.js Javascript plugin, which is a code highlighter. When using the plugin, we place code inside “pre” and “code” tags and pass language hints via specific CSS classes (e.g language-python). Here is what our snippet could look like:
snippet pr "Pre-code section" A <pre> <code class="language-${1:python}">$0</code> </pre> endsnippet
In the example above you can see we used the “$0” tabstop: it has a special meaning, since it is always considered as the last one. If it is not explicitly used, it is automatically added at the end of snippets. We save the code in the ~/.vim/UltiSnips/html.snippets
file. Let’s see how it works:

Once again we entered Vim insert mode by pressing “i”. This, time the snippet expanded as soon as we typed “pr” (the snippet trigger), even if we didn’t use the “ExpandTrigger” key. This happened because we used the “A” option (Automatic) in the snippet definition.
As expected, the default value of the $1 tabstop is selected (“python”). In this case we replaced the text with “bash”. By pressing Ctrl+j we moved the cursor to next tabstop (inside the <code>
and </code>
tags). where we written our code.
Conclusions
In this tutorial we learned how to manage snippets in Vim with the UltiSnips plugin. We saw how to install the plugin together with some predefined snippets and we learned how to write our own. UltiSnips is a very powerful plugin; to learn how to use it at its full potential, beside reading the official documentation, you can watch some video tutorials linked in the project page on Github.