There are a few options for you, depending on what exact settings you'd like to tweak, how you'd like to manage them and whether you're worried about untrusted settings.
Use "editorconfig"
If the kinds of settings you would like to set are related to indentation style, tab size, file format and charset, then you might want to look into "editorconfig", which is a cross-editor standard to specify this kind of settings in a specific project, and have all editors follow that configuration.
The "editorconfig" specification allows projects to request different settings depending on file extensions or names within the project. (So you can have Makefiles using TABs, your Python scripts using 4 spaces and your shell scripts using 2 spaces for indentation.)
You need a plug-in to use "editorconfig" in Vim. The official website provides one, but personally I'd recommend sgur/vim-editorconfig, which is written in pure Vimscript, so you don't need to worry about external dependencies too much.
Since "editorconfig" aims at cross-editor compatibility, it's quite limited in what it does, so if you want is consistent whitespace, file format (DOS vs. Unix) and encoding (Unicode utf-8, etc.), then "editorconfig" is for you. Otherwise, maybe not.
An autocmd
in your .vimrc
Second choice is to manage project settings from your actual vimrc. If you have a single project, or at most a handful, that need this kind of setup, then that's possibly an option.
In order to do that, use :autocmd
, looking for events BufRead
and BufNewFile
and use a pattern that matches files under your project tree.
(Always put your :autocmd
s inside an :augroup
, since then they won't be duplicated whenever you :source
your vimrc again.)
For example:
augroup myproject
autocmd!
autocmd BufRead,BufNewFile ~/myproject/* set ft=myproject
autocmd BufRead,BufNewFile ~/myproject/*.py set ft=mypython
augroup END
This will set the filetype to mypython
for all the files with the py
extension in your project, and the myproject
filetype for all other files under that project.
See :help file-pattern
for more details in how you can specify the matching pattern for the BufRead
and BufNewFile
events. In particular, the *
will match path separators (/
), so this will work recursively in subdirectories of your project.
It's likely that you might have multiple autocmd
s fighting for the filetype of a specific type (for example, Vim default runtime will try to make the *.py
files use the python
filetype.) Which one will win will depend on a few factors, including ordering. Typically the rules in your vimrc will be the earliest ones, but that's no longer the case if you source your vimrc and recreate those rules.
You have three options to set the filetype:
set filetype=mypython
: This will always set the filetype, at that point. It will only be lost if it's overwritten by another set filetype=...
command. This is what you should typically use in your setup if you want to enforce your filetype.
setfiletype mypython
: This will set the filetype, but only if it was unset at that point. This is typically what Vim's basic runtime and also plugins will use, so if you make your own setting, it will be stronger than these. (So, if all plugins are behaving correctly, you should be good!)
setfiletype FALLBACK mypython
: This will set the filetype, only if it's still unset. But if there's another setfiletype
the latter will override it. So this is a good way to set a fallback filetype, if the file doesn't get one in a different way.
You probably want either option 1 (if you want to control the final filetype), or option 3 (if you just want a fallback, for files that don't otherwise get a filetype.)
Finally, once you set filetypes, you can use the normal per-filetype configuration to set specific options and configure keybindings and commands for them. Just create the appropriate scripts under ftplugin/
in your ~/.vim/
directory, named after your filetype, and add your setlocal
, nnoremap <buffer>
, etc. commands there.
Using 'exrc'
and 'secure'
You could enable the 'exrc'
option in your vimrc. If you do so, make sure you also enable 'secure'
, which typically needs to be set at the end of the vimrc file.
set exrc
set secure
This will instruct Vim to read a vimrc file (.vimrc
or _vimrc
) from your current directory. So you could use this to set a per-project vimrc.
If you always cd to the top of the project, and refer to files in subdirectories by their full path, then a single .vimrc
at the top of the project might be enough. If you typically cd into subdirectories, you might want to keep symlinks to the .vimrc
at the top from subdirectories (which is not great, but possibly something you could automate.)
There are many drawbacks with this solution, such as still having to solve subdirectories, having to be inside the project tree when you start Vim and also security concerns about sourcing .vimrc
files from the tree (you're setting 'exrc'
globally, so Vim will try to open any .vimrc
you happen to stumble upon.)
This is a terrible idea. Don't go with this one!
Roll your own
Finally, you could roll your own solution. That might take some Vimscript to do, but you can probably come up with something that fits your exact requirements.
You can probably get some inspiration from "editorconfig" in searching for the config file up the tree, and maybe its basic file format. (Perhaps just extend it for whatever else you might want to configure? Perhaps so that you can set a 'filetype'
?)
This would take a bit of work, but I think the idea has potential.
Hopefully one of these options will be close enough to what you'd like.