Vim is a text editor and is an improvement of the original ‘vi’ program. All ‘vim’ examples presented in this tutorial were tested using version 8.1. Older versions might not work as expected.

Vim and Neovim

NeoVim is a ‘vim’ fork designed to improve the user experience. NeoVim supports the same features than ‘vim’ offering additional features. Plugins designed for ‘vim’ usually work on ‘neovim’ as well even though the latter implements a different plugin architecture based on RPC calls.

Disabling Vim backward compatibility with Vi

Before proceeding, one should make sure the ‘nocompatible’ option is turned on:


Which should produce the following:

filetype detection:ON plugin:ON indent:ON

Should the output not match:

set nocompatible
filetype plugin indent on
Enabling the Python support for Vim

In order to check which version of Python is supported by ‘vim’:


Either the string ‘+python’ or ‘+python3’ will be printed, according to the supported Python version. NeoVim instead, is able to support both, Python 2 and Python 3 at the same time. To test whether the ‘neovim’ installation supports Python 3:

:py3 print('test')

The command above prints the string ‘test’, should Python 3 be supported. If an error is returned, the Python 3 provider can be installed as follows:

$> pip3 install --user --upgrade neovim
Automating Vim using scripts

Automation can be achieved though scripts. The following can be used to automate the previous test:

function! TestPython()
   :py3 print('test')
command! TestPython call TestPython()

Save the previous lines into a file called, for example:


In ‘vim’, the following line will load the script in memory:

:source ~/.vim/vim_scripts/pythontest.vim

The next one prints all available scripts:


Next, the following will execute the script:


Adding the following to the script will create a shortcut: now the user will just need to type T to execute the code:

nnoremap T :TestPython<CR>
Creating plugins for Vim

Plugins can be used to share useful scripts with other developers, keeping the code organised. To turn scripts into plugins one needs to create the following directory structure:

|→ doc/
    |→ [plugin_name].txt
|→ plugin/
    |→ [plugin_name].vim

To install a plugin, one needs to append the plugin path to ‘runtimepath’:

:set runtimepath+=~/.vim/[plugin_path]

To double-check the value of ‘runtimepath’:

:echo join(split(&runtimepath, ','), ", ") 
Creating packages for Vim

Packages are collections of plugins. To create a package one needs to:

  1. Create a directory with the name of the package.
  2. Create a sub-directory called ‘start’.
  3. Copy all plugins to ‘start’ in the package tree.
  4. Move the package under ‘~/.vim/pack’ where the system automatically finds and load packages.

While all plugins stored into the ‘start’ package directory are always loaded, those that are only seldom necessary can be saved into the ‘opt’ directory ready to be loaded when needed. After having copied an optional plugin into the ‘opt’ package directory, the following command loads it into memory:

:packadd [plugin_name]

Many plugin managers do exist for ‘vim’:

  1. vundle.
  2. vim-plug.
  3. minpac.

These can be used to update, install, run, configure and delete plugins.

Locating files quickly in Vim using plugins

Many ‘vim’ plugins can be used in order to quickly locate files to manipulate:

  1. projectionist, searches for files semantically according to its configuration file.
  2. vim-find-files, searches for files showing results in many different ways.
  3. vim-finder, searches for files matching tags, lines and much more.
  4. fzf, searches for files using fuzzy path matching which is ideal when the input is very large.
The Projectionist plugin

To install the projectionist plugin the reader will create a package named ‘internet’ to save all plugins taken form the internet. As already explained, this directory will contain a ‘start’ sub-folder which is used to store the plugin:

$> cd ~/.vim/pack
$> mkdir -p internet/start
$> cd internet/start

Let’s retrieve the plugin code from the internet (bear in mind that the provided address might vary over time):

$> git clone

Let’s setting the plugin up:

$> vim -u NONE -c "helptags projectionist/doc" -c q
Managing alternate files with the Projectionist plugin

Alternate files are files that are somehow related to each other. For example, a release manager could create multiple configuration files, each one for each environment:

  1. Config-Development.xml
  2. Config-Test.xml
  3. Config-PreProduction.xml

Let’s create the following directory structure:

├── bin
│    └── execute_me
├── config
│    ├── dev.xml
│    ├── prod.xml
│    └── test.xml
└── js
     ├── dev.js
     ├── prod.js
     └── test.js

In the ‘application’ directory, a file called ‘.projections.json’ with the following content is to be created:

    "bin/execute_me": { "type": "exec" },
    "config/*.xml": { "type": "config" },
    "js/*.js":{ "type": "script" }

In the ‘application’ directory, in a ‘vim’ session, the following command will open the file ‘execute_me’:


Let’s open ‘config/dev.config’:

:Econfig dev 

Let’s improve the ‘.projections.json’ file:

    "bin/execute_me": { "type": "exec" },
    "config/*.xml": { "type": "config" },
    "config/dev.xml": { "alternate": "config/test.xml" },
    "config/test.xml": { "alternate": "config/dev.xml" },
    "config/prod.xml": { "alternate": "config/test.xml" },
    "js/*.js": { "type": "script" },
    "js/dev.js": { "alternate": "js/test.js" },
    "js/test.js": { "alternate": "js/dev.js" },
    "js/prod.js": { "alternate": "js/test.js" }

To open ‘config/dev.xml’:

:Econfig dev

Let’s switch to its alternate file, ‘config/test.xml’:

Watch this tutorial on YouTube


Previous Post Next Post