How to switch between multiple vim configurations with a command or local vimrc files?

Vim

Vim Problem Overview


I work in several groups, each of which has its own tab/indentation/spacing standards in C.

Is there a way to have separate selectable VIM configurations for each so, when I edit a file, either:

  • I do something like set group=1 to select a configuration
  • a local .vimrc that lives in the working directory is used to set the configuration automatically

Vim Solutions


Solution 1 - Vim

I have this in $HOME/.vimrc:

if filereadable(".vim.custom")
    so .vim.custom
endif

This allows me to put a .vim.custom file in every directory to load commands and options specific to that directory. If you're working on multiple projects that have deep directory structures you might need something more sophisticated (e.g. walk up the directory tree until a .vim.custom is found), but the same basic idea will work.

UPDATE:

I now do something like this in order to read a .vim file from the same directory as the file I'm editing, regardless of what the current directory is.

let b:thisdir=expand("%:p:h")
let b:vim=b:thisdir."/.vim"
if (filereadable(b:vim))
    execute "source ".b:vim
endif

Solution 2 - Vim

In Summary

There are a few ways to do this, of which most have been suggested, but I thought I'd summarise them with two extra ones:

  • Per-directory vimrc - has the disadvantage that Vim must be started in the right directory: if your project is in ~/project1 and you have ~/project1/.vim.custom and do cd ~ ; vim project1/file.c, the custom settings won't be found.
  • Modelines - very effective, but has the disadvantage of needing to add them to all files (and remember to add them to new files)
  • Directory specific autocommands - this is very effective
  • Scan for a specific header in the file (see below) - this is the one I've used most in the past where working for different companies or on clearly named projects
  • Per-directory vimrc that's checked when the file is opened (see below). Another fairly easy one to implement, especially if your project code is all in one place.

Scanning for a Header

In a lot of organisations, there's a standard header (with a copyright notice and project name etc) at the top of every source file. If this is the case, you can get Vim to automatically scan the first (e.g.) 10 lines of the file looking for a keyword. If it finds it, it can change your settings. I've modified this to make it simpler than the form I use (which does lots of other things), but create a ~/.vim/after/filetype.vim (if you don't have one yet) and add something like this:

au FileType * call <SID>ConfigureFiletypes(expand("<amatch>"))

" List of file types to customise
let s:GROUPNAMETypes = ['c', 'cpp', 'vhdl', 'c.doxygen']

func! <SID>CheckForGROUPNAMECode()
	" Check if any of the first ten lines contain "GROUPNAME".
	
	" Read the first ten lines into a variable
	let header = getline(1)
	for i in range(2, 10)
		let header = header . getline(i)
	endfor

	if header =~ '\<GROUPNAME\>'
		" Change the status line to make it clear which
		" group we're using
        setlocal statusline=%<%f\ (GROUPNAME)\ %h%m%r%=%-14.(%l,%c%V%)\ %P
        " Do other customisation here
        setlocal et
        " etc
	endif
endfunc

func! <SID>ConfigureFiletypes(filetype)
	if index(s:GROUPNAMETypes, a:filetype) != -1
		call <SID>CheckForGROUPNAMECode()
	endif
endfunc

Whenever a file of any type is opened and the file type is set (the au FileType * line), the ConfigureFiletypes function is called. This checks whether the file type is in the list of file types associated with the current group (GROUPNAME), in this case 'c', 'cpp', 'vhdl' or 'c.doxygen'. If it is, it calls CheckForGROUPNAMECode(), which reads the first 10 lines of the file and if they contain GROUPNAME, it does some customisation. As well as setting expandtabs or whatever, this also changes the status bar to show the group name clearly so you know it's worked at a glance.

Checking for Configuration When Opening

Much like JS Bangs' suggestion, having a custom configuration file can be useful. However, instead of loading it in vimrc, consider something like this, which will check when a .c file is opened for a .vim.custom in the same directory as the .c file.

au BufNewFile,BufRead *.c call CheckForCustomConfiguration()

function! CheckForCustomConfiguration()
    " Check for .vim.custom in the directory containing the newly opened file
    let custom_config_file = expand('%:p:h') . '/.vim.custom'
    if filereadable(custom_config_file)
        exe 'source' custom_config_file
    endif
endfunction

Solution 3 - Vim

You can also put autocommands in your .vimrc which set specific options on a per-path basis.

au BufRead,BufNewFile /path/to/project1/* setl sw=4 et
au BufRead,BufNewFile /path/to/project2/* setl sw=3 noet

Solution 4 - Vim

Plugin doing the right thing: http://www.vim.org/scripts/script.php?script_id=441

“This plugin searches for local vimrc files in the filesystem tree of the currently opened file. By default it searches for all ".lvimrc" files from the file's directory up to the root directory and loads them in reverse order. The filename and amount of loaded files is customizable through global variables.”

Solution 5 - Vim

Assuming your fellow developers won't complain about it, you can always add vim settings to each file in the comments.

/*
 * vim:ts=4:sw=4:expandtab:...
 */

int main(int argc, char **argv)
{
    ...

Solution 6 - Vim

I created an open-sourced tool for just this purpose. Forget the headers, scanning, configurations, and local vimrc files.

Try swim.


Swim

swim is a quick tool for switching vimrc files and creating convenient aliases. Here's a short usage list. See the Github repo for a walkthrough gif and download instructions:


Usage
swim add ~/dotfiles/myVimrc favorite    #Add new swim alias
swim ls                                 #Show available swim aliases
swim add https://raw.githubusercontent.com/dawsonbotsford/swim/master/exampleVimrcs/vimrcWikia.vim example
swim with favorite         #Set alias favorite as primary .vimrc
swim with main             #Set alias main as primary .vimrc


Read More

https://github.com/dawsonbotsford/swim

Solution 7 - Vim

After trying out the localvimrc plugin suggested by the previous poster, I very much like having non-futzy per-project control over vim settings.

It does ask confirmation before loading a .lvimrc file by default but there is a setting to automatically load .lvimrc files. Some might see this as a security hole, but it works as advertised.

I chose to .gitignore the .lvimrc files. Alternatively you can check them in as a form of shared settings (tab/space expansion, tabstops, other project-specific settings).

Solution 8 - Vim

As mentioned by sledge the usage of that plug-in is the best option I have seen and use. jerseyboy commented that the utility recommended ask for confirmation before loading (ie. after opening every file). To avoid this just set at your main .vimrc the list of local .lvimrc files:

let g:localvimrc_whitelist='/development/kernel/.lvimrc'

Solution 9 - Vim

Here's a variation on jamessan's

function! ConditionalLoad()
    let cwd = getcwd()
    if getcwd() =~ $HOME . "/src/mobile"
        so $HOME/.vim.mobile
    endif
endfunction
autocmd VimEnter * call ConditionalLoad()

I will frequently launch vi without a specific file that I'm jumping to so this enables loading config conditionally based on the current working directory. Downside is that the config isn't applied based on file but off of working directory.

Solution 10 - Vim

> I work in several groups, each of which has its own tab/indentation/spacing standards in C.

I work with all sorts of open source, all at the same time. It's not practical to be creating separate .vimrc files and reconfiguring the formatting standards. More than a decade ago, I finally got tired of dealing with the editor configuration and wrote a program called autotab to handle it.

When autotab is set up with Vim suggested, each time you load a file into Vim, autotab is invoked on it, and the Vim settings output autotab are passed to a :set command.

autotab reads several thousand lines from the file, analyzes them and determines the settings for the expandtab, tabstop and shiftwidth parameters.

It figures out whether the file uses hard tabs or just spaces for indentation, and it figures out the indentation size. If the file is indented with tabs, it figures out the right tab size, based on rendering the file sample using various tab sizes and judging it according to heuristics like line-over-line alignment of internal elements.

It works well enough that I stopped tweaking the algorithm years ago. If it gets confused, it's almost always because the file has formatting issues, such as the use of multiple conventions at the same time.

It is also "agnostic" of the file type and works well with a variety of different languages. I use it not only over C, but shell scripts, Lisp, Makefiles, HTML, and what have you.

Note that it doesn't handle other parameters of formatting that may be project-specific, like for instance, in C files, whether case labels in a switch statement are indented or not, or whether wrapped function argument lists are simply indented, or aligned to the opening parenthesis of the argument list. Vim does have settings for that sort of thing, and so the program could be plausibly extended to analyze the style and output those parameters.

Solution 11 - Vim

Looking for mostly the same issue I also found the Sauce plug-in: http://www.vim.org/scripts/script.php?script_id=3992

It claims: >Sauce is a lightweight manager for multiple vimrc files, which can be used to load different settings for different environments. In short, you can maintain lots of different vim settings files and only load the one(s) you need when you need them.

I find it particularly interesting that it keeps it configuration all in its data directory instead of expecting the user to sprinkle dotfiles across the filesystem. This though often rather a metter of personal taste.

I have yet to test it though.

Solution 12 - Vim

You can use stow for switching configuration (any dotfiles, not only .vimrc)

Install stow:

$ apt install stow

Create multiple directories for each configurations:

~$ ls -d ~/dotfiles/vim*
vim-all vim-webdev vim-go

Put different .vimrc's in them:

$ find ~/dotfiles -name .vimrc
/home/username/vim-golang/.vimrc
/home/username/vim-webdev/.vimrc
/home/username/vim-all/.vimrc

Now you can instantinate vim-golang config with this command (should be run inside dotfiles directory):

~$ cd ~/dotfiles

dotfiles$ stow -v vim-golang
LINK: .vimrc => dotfiles/vim-golang/.vimrc

Now it's linked:

$ cd ~ && ls -l .vimrc 
.vimrc -> dotfiles/vim-golang/.vimrc

If you need to switch config, just re-stow it:

~$ cd dotfiles

dotfiles$ stow -v -D vim-golang
UNLINK: .vimrc

dotfiles$ stow -v vim-webdev
LINK: .vimrc => dotfiles/vim-webdev/.vimrc

$ cd ~ && ls -l .vimrc 
.vimrc -> dotfiles/vim-webdev/.vimrc

More reading of it here: Managing dotfiles with GNU stow

Pros: pretty simple, no vim plugin dependencies, can be used for managing all dotfiles, not only .vimrc.

Cons: configs are independent of each other, you need to manage/update each of them separately (if you dont switch/update you configs too often - it'll not be the issue).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbradreavesView Question on Stackoverflow
Solution 1 - VimJSBձոգչView Answer on Stackoverflow
Solution 2 - VimDrAlView Answer on Stackoverflow
Solution 3 - VimjamessanView Answer on Stackoverflow
Solution 4 - VimsledgeView Answer on Stackoverflow
Solution 5 - VimJim MitchenerView Answer on Stackoverflow
Solution 6 - VimDawson BView Answer on Stackoverflow
Solution 7 - VimjerseyboyView Answer on Stackoverflow
Solution 8 - VimjekikView Answer on Stackoverflow
Solution 9 - VimMichael WasserView Answer on Stackoverflow
Solution 10 - VimKazView Answer on Stackoverflow
Solution 11 - VimrfindeisView Answer on Stackoverflow
Solution 12 - VimkibaView Answer on Stackoverflow