Vim/Neovim — Managing Multiple Project Settings

Managing project-specific settings for Vim/Neovim projects.

Photo by Octavian Dan on Unsplash

Overview

I talked about managing multiple databases and projects in my previous articles. On some occasions, you may have a need to manage multiple projects with configurations only specific to the projects.

In this article, let’s explore the available options we have in Vim/Neovim. I will start with the simplest solution and then move on to explore plugins we can use.

exrc, vimrc, nvimrc

If you set the exrc option in your .vimrc or init.vim file, Vim/Neovim will execute .exrc (for both Vim/Neovim), .vimrc (Vim), .nvimrc (Neovim) found in the current directory when Vim/Neovim is started.

set exrc

For security reason, you may also want to set the secure option together (refer to :h secure)

set secure exrc

When secure is on, :autocmd, shell and write commands are not allowed in .nvimrc, .vimrc and .exrc in the current directory and map commands are displayed.

From the documentation for the secure option,

When on, “:autocmd”, shell and write commands are not allowed in
“.nvimrc” and “.exrc” in the current directory and map commands are
displayed. Switch it off only if you know that you will not run into
problems, or when the ‘exrc’ option is off. On Unix this option is
only used if the “.nvimrc” or “.exrc” is not owned by you. This can be
dangerous if the systems allows users to do a “chown”. You better set
‘secure’ at the end of your |init.vim| then
.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.

Per Neovim documentation for exrc option,

If the 'exrc' option is on (which is NOT the default), the current
directory is searched for two files. The first that exists is used,
the others are ignored.
- The file ".nvimrc"
- The file ".exrc"

Per Vim documentation for exrc option,

If the ‘exrc’ option is on (which is NOT the default), the current
directory is searched for three files. The first that exists is used,
the others are ignored.
— The file “.vimrc” (for Unix, Amiga) (*)
“_vimrc” (for Win32) (*)
— The file “_vimrc” (for Unix, Amiga) (*)
“.vimrc” (for Win32) (*)
— The file “.exrc” (for Unix, Amiga)
“_exrc” (for Win32)

Plugins for Local vimrc

Alternatively, you can use plugins to enable per-directory configurations. You can make use of vim-localvimrc and vim-localrc for this purpose, which may be more secure than setting exrc.

Built-in FileType Plugin

If your projects are of different languages, one good option is definitely to make sure of the built-in file type plugin (:h ftplugin).

For Vim, the folder to use is normally under ~/.vim/after/ftplugin. E.g. if you want to override the default Javascript settings, create a file called javascript.vim in this folder with the custom settings.

For Neovim, the folder to use is normally under ~/.config/nvim/after/ftplugin.

E.g. if you go to the default system ftplugin folder (In my case is /usr/local/share/nvim), you can see the default configurations for all file types.

Default File Type Plugins for Neovim

AutoCmd

Another option is to use the auto command. There are multiple ways you can use it.

Language-Specific Settings

You can set language-specific setting, e.g.

autocmd FileType markdown setlocal spell
autocmd FileType html setlocal shiftwidth=2
autocmd FileType php,html setlocal shiftwidth=2 expandtab

Or you can source a file if you have many settings, e.g.

autocmd FileType markdown source ~/.vim/settings/mysettings.vim

Centralized Settings

You can also centralize your settings to a folder using the auto command (:h autocmd-pattern), e.g.

:autocmd BufRead,BufNewFile /path/to/dir/** setlocal ts=4 sw=4

Also, read this chapter fromLearn Vimscript the Hard Way to understand the pitfall of auto command, and how to avoid creating duplicate auto commands.

editor-config

editorconfig-vim is an EditorConfig plugin for Vim/Neovim. Basically, you just need to create an .editorconfig file in the project folder and Vim/Neovim will use the settings using this plugin.

The EditorConfig Vim plugin supports the following EditorConfig properties:

  • indent_style
  • indent_size
  • tab_width
  • end_of_line
  • charset
  • insert_final_newline
  • trim_trailing_whitespace
  • max_line_length
  • root (only used by EditorConfig core)

From Vim/Nevom, type :h editorconfig to get more details from the documentation once you installed it,

vim-sleuth

This plugin may not allow you to manually configure project-specific settings. vim-sleuth automatically adjusts 'shiftwidth' and 'expandtab' heuristically based on the current file, or, in the case the current file is new, blank, or otherwise insufficient, by looking at other files of the same type in the current and parent directories.

vim-projectionist

projectionist.vim provides granular project configuration using “projections”.

Let’s see a trivial example to set a color scheme for a project.

Create a file called .projections.json in a folder with the following content.

{
"*.html": {
"colorscheme": [
"onedark"
]
}
}

Projectionist will detect this file and set a buffer-local variable (b:projectionist) whenever an HTML file is loaded.

b:projections Variable

Using the dofiles I developed in my previous article, create a plugin/projectionist.vim file with the following content.

augroup change_colorscheme
autocmd!
autocmd User ProjectionistActivate call s:change_colorscheme()
augroup END
function! s:change_colorscheme() abort
let l:colorscheme = projectionist#query('colorscheme')
if len(l:colorscheme) > 0
execute 'colorscheme '.l:colorscheme[0][1][0]
endif
endfunction

Restat Vim/Neovim, and now if you open or create an HTML file in the folder the color scheme will automatically change to onedark.

HTML with OneDark Theme

Projectionist also has features that make navigating project easier.

E.g. with the following .projections.json which describes my project structure, I can navigate the project files easily.

{
"*.html": {
"colorscheme": [
"onedark"
]
},
"libs/*.py": {
"alternate": "tests/test_{}.py",
"type": "source"
},
"tests/test_*.py": {
"alternate": "libs/{}.py",
"type": "test"
},
"cli.py": {
"type": "main"
},
"lib/models/*.py": {
"type": "model"
}

}
A Simple Project Structure

Now,

  • type :Emain will open cli.py
  • open utils.py, type :A and test_utils.py will be loaded.
  • open test_utils.py, type :A and utils.py will be loaded.
  • type :Emodel users and users.py will be loaded.

You have various options to open the file in split, tab, etc. Type :h projectionist to look at the documentation.

If you are looking for a Lua-based plugin you can try out vim-projectconfig.

Do also check out the following articles!

Programmer and occasional blogger.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store