Per project/tree configuration plugins
The aim of
local_vimrcis to apply settings on files from a same project.
A project is defined by a root directory: everything under the root directory belongs to the project. No need to register every single file in the project, they all belong.
This plugin presents a solution to Yakov Lerner's question on Vim ML. It searches for
_vimrc_local.vimfiles in the parents directories and sources the one found.
Is it possible, after sourcing ~/.exrc, to traverse from
$HOMEdown to cwd, and source.exrcfrom every directory if present ? (And if cwd is not under$HOME,just source~/.exrc). What do I put into .vimrc to do this ?Example: current dir is
~/a/b/c. Files are sourced in this order: ~/.exrc, then ~/a/.exrc,~/a/b/.exrc,~/a/b/c/.exrc. No messages if some of.exrcdoes not exist.
The latest version of this script requires vim 7.0 and lh-vim-lib v5.2.1+. UT v0.1.0 will be required to execute the unit tests.
The easiest way to install this plugin is with vim-addon-manager, or other plugin managers based on vim-pi, that support vim-addon-files -- as this script specifies its dependencies in vim-addon-file format.
ActivateAddons local_vimrc
Or with vim-flavor which also supports dependencies:
flavor 'LucHermitte/local_vimrc'
With Vundle
Plugin 'LucHermitte/lh-vim-lib' Plugin 'LucHermitte/local_vimrc'
Or, with a NeoBundle version that doesn't support vim-pi yet: ```vim set rtp+=~/.vim/bundle/NeoBundle.vim/ call neobundle#begin(expand('~/.vim/bundle')) NeoBundleFetch 'Shougo/NeoBundle.vim' " Line required to force the right plugin name -> lh-vim-lib, and not trunk NeoBundle 'LucHermitte/lh-vim-lib', {'name': 'lh-vim-lib'} " Note: I haven't found the syntax to merge the two NeoBundle lines into one... NeoBundle 'LucHermitte/local_vimrc', {'depends': 'lh-vim-lib'} call neobundle#end()
NeoBundleCheck ```
Drop a
_vimrc_local.vimfile into any project root directory, and write it exactly as you would have written a ftplugin.
_vimrc_local.vimcontent
In other words. The project file is expected to be loaded (/sourced) every time you enter a buffer that corresponds to a file under the project root directory.
As a consequence, you may want to prevent multiple executions of parts the sourced file: almost everything shall remain identical and shall not need to be reset. However some plugins, like alternate (a.vim), rely on global variables to tune their behaviour. The settings (global variables) related to those plugins will require you to update their value every time -- if you expect to have settings that differ from a project to another. In order to support such project-aware setting,
local_vimrclets you in charge of handling anti-reinclusion guards in project configuration files.
For your project settings prefer buffer-local mappings (
:h :map-), abbreviations (
:h :abbreviate-), commands (
:h :command-buffer), menus (see my fork of buffer-menu), settings (
:h :setlocal), and variables (
:h local-variable).
N.B.: if you are a plugin writer that want to support configuration variables that'll dynamically adapt to the current project settings, have a look at my
lh#option#get()and
lh#ft#option#get()functions.
You'll find examples of use in my dedicated repository.
The behaviour of this plugin can be tuned with the following options:
g:local_vimrcvariable specifies the filenames and filepaths to be searched. The default is
"_vimrc_local.vim". It can contain a list (
:h List) of pathnames, or a simple string. It's meant to contain something that'll be relative to your current project root.
_vimrc_local.vimin directories named
.config/at the root of current project directory, set the variable to
vim let g:local_vimrc = ['.config', '_vimrc_local.vim']
g:local_vimrc_optionsdictionary will hold four lists (
whitelist,
blacklist,
asklist, and
sandboxlist) that define how security issues are handled. See Security concerns.
Sometimes we want to set variables (like a project source directory, or
specific template files that override the default project file headers) before
other plugins are triggered.
The typical use case will be from the shell:
```
cd /path/to/myproject/submodule42 gvim foobar.h ```
In order to use
myprojectsettings (naming styles, header guards naming policy, ...), the
vimrc_localfile needs to be sourced before any template-file is expanded.
This plugin provides the
:SourceLocalVimrccommand for this purpose. It's up to the Template Expander Plugin to exploit this feature -- as this moment, only my fork of mu-template does.
vimrc_localscript version number
When saved, if the
vimrc_localscript has a
s:k_versionvariable, it will be incremented automatically. This variable is meant to avoid multiple inclusions of the script for a given buffer. New
vimrc_localscripts created with the help of the templates provided with my mu-template fork are making use of this variable.
Thanks to the option
g:local_vimrc_options, it's possible to tune which
_vimrc_localfiles are sourced, and how.
The four lists
g:local_vimrc_options.whitelist,
g:local_vimrc_options.blacklist,
g:local_vimrc_options.asklist, and
g:local_vimrc_options.sandboxlist, will hold lists of pathname patterns. Depending on the kind of the pattern that is the best match for the current
_vimrc_localfile, the file will be either:
:h sandbox) if it belongs to the sandboxlist.
_vimrc_localfile in
$HOME/.vim/will be sourced.
$HOME/.vim/subdirectories will be ignored. This way, the end-user may specify options to use when editing vim files. See the file I use for instance.
_vimrc_localfiles under
$HOMEare sourced only if the end-user interactively says "yes".
_vimrc_localfiles under
$HOME/..are ignored.
In order to blindly accept
_vimrc_localfiles from projects your are working on, you'll have to add this kind of lines into your
.vimrc, after this plugin has been loaded:
" Sourcing the plugin ActivateAddons local_vimrc ... " Let's assume you put all projects you are working on in your " corporation under $HOME/dev/my_corporation/ call lh#local_vimrc#munge('whitelist', $HOME.'/dev/my_corporation') " But projects from 3rd parties/projects downloaded from the internet go " into $HOME/dev/3rdparties/ call lh#local_vimrc#munge('blacklist', $HOME.'/dev/3rdparties')
If you want to override default settings, change them in your
.vimrcafter this plugin has been loaded. e.g.:
ActivateAddons local_vimrc ... " Remove $HOME from the asklist, call lh#local_vimrc#filter_list('asklist', 'v:val != $HOME') " Add it in the sandbox list instead call lh#local_vimrc#munge('sandboxlist', $HOME)" Clean the whitelist let lh#local_vimrc#lists().whitelist = []
To be fair, there exist alternatives.
Modelines are particularly limited: * We can't set variables (that tunes other (ft)plugins, like "should the braces of the for-snippet be on a newline ?"), * nor call functions from modelines (I don't limit myself to coding standards, I also set the makefile to use depending on the current directory) * Modelines aren't DRY. With modelines, a setting needs to be repeated in every file, if there are too many things to set or tunings to change, it will quickly become difficult to maintain, moreover, it will require the use of a template-expander plugin (which you should consider if you have several vimmers in your project). * Not every one uses Vim to develop. I don't want to be bothered by other people editor settings, why should I parasite theirs with modelines ?
.exrc
Vim natively supports
.exrcfiles (
:h .exrc, § d-) when
'exrc'is on. This solution is very similar to
local_vimrc. However
.exrcfiles are executed (sourced in Vim jargon) only on buffers (corresponding to files) which are in the exact same directory. Files in subdirectories won't trigger the execution of the project
.exrcfile.
It's possible to add autocommands in our
.vimrc. Autocommands that will detect files under a certain directory to trigger commands (
:set xxxxx,
:let b:style='alman',
:source path/to/project_config.vim, ...).
If the autocommand executes simple commands (instead of sourcing a file), the solution won't scale when new commands will need to be added.
Autocommands won't scale either as a project location may vary : * On several machines a project may not be stored in the same path ; * When branches are stored in different paths, the
.vimrcmay need to be tuned for each branch ; * When several people are using Vim, it's easier to ask them to install a same plugin instead of asking them to maintain and adapt their respective
.vimrc
There exist a quite old (which does NOT mean bad) plugin dedicated to the management of project configuration. I've never used it, I won't be able to tell you why
local_vimrcsolution is better or not.
There exist many plugins with the same name or even with similar purpose. Just to name a few, there is for instance:
Project oriented plugins:
local-vimrc plugins:
local_vimrccan be used with BuildToolsWrapper to support CMake based projects.
local_vimrc
vimrc_localscripts
is_eligibleon the right pathname (PR#12)
! lh#project#is_eligible()
g:local_vimrcis a string.
lh#local_vimrc#verbose(1)
s:k_versionin
vimrc_localfiles is automatically incremented on saving.
:SourceLocalVimrcin order to explicitly load the local-vimrc file before creating new files from a template (We can't just rely on
BufNewFileas there is no guaranty
vimrc_local's
BufNewFilewill be called before the one from the Template Expander Plugin => it's up to the TEP to call the function).
LocalVimrc
//or
\\(UNC paths)
'verbose' >= 2
$HOMEor at root (
/)
_vimrc_local.vim