Vim: apply settings on files in directory - vim

How do I specify Vim settings for all files under the current directory?
The ideal solution would be if Vim searched for and read a .vimrc in the current directory before searching for ~/.vimrc, and apply the settings there for the entire tree.
I've seen a plugin, but this means the applied settings aren't transparent since they require the plugin to be installed. In contrast, a modeline is transparent since regardless of a user's vimrc or specific vim invocation the modeline settings will be applied for that file.
Things I tried are
placing a .vimrc in the working directory
:so vimrc in the modeline.
I suppose both don't work for security reasons. I don't need the full power of a vimrc; being bound to settings acceptable by a modeline would suffice. My goal is to make it easier for vimmers to adopt coding standards in a project.

You can put something like this in $VIM/vimrc
autocmd BufNewFile,BufRead /path/to/files/* set nowrap tabstop=4 shiftwidth=4

I'd strongly suggest not using set exrc
Even with set secure, under *nix, vim will still run autocommands, shell, et al, if you own the file. So if you happend to edit a file in that tarball I sent you with a .vimrc containing:
autocmd BufEnter * :silent! !echo rm -rf ~/
you'll probably be less amused than I will.

I'm an advocate of the plugin way.
For several reasons:
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 ?"), or call function from them (I don't limit myself to coding standards, I also set the makefile to use depending on the current directory)
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?
It's easier to ask vimmers to install a same plugin, instead of asking them to copy-paste, and maintain, the same lines in their .vimrc
The settings can be saved with the other project files (cvs/svn/git/whatever)
It's really easy to have a configuration file per project -- with the plugin, I have a global configuration file for the coding standards of the overall project, and specific configuration files for each sub-project (which makefile to use, which executable to call, ...)
BTW, sth's solution can be used to source a single configuration file. This is very similar to the plugin approach except the .vimrc has to be parasited with non global options, and it does not support easily multiple/shared configuration files.

This question is old, but it seems like a pretty natural and persistent concern.
My solution is pretty simple. I place a .vimrc file in the root directory of my projects. The first line of the .vimrc file usually sources ~/.vimrc, and then adds the particular configuration I want. I alias tvim='vim -u .vimrc', and use tvim in my personal project directories. "tvim" for "trusted vim," meaning that if I execute it in a directory with a .vimrc file and something goes wrong, I've got no one to blame but myself, since I explicitly said I trusted it. Also, I keep a group of these stored away so that I can sometimes just softlink the one I want for a particular kind of project.

Placing a .vimrc in the working directory actually is supported, only disabled by default. See :h 'exrc' and :h startup for details, setting 'exrc' will enable reading .vimrc from the current directory.
It's also recommended to :set secure when using this. This locks down :autocmd, shell and write commands for .vimrc in the current directory.
Another thing that might be worth looking at is setting up a session (:h session) with a standard view and settings for the project.
All that said, I would probably go with the plugin option detailed by Luc Hermitte myself.

To minimize security risks with ANY "autorun" features for ANYTHING these days, may I advise you to utilize vim's existing features instead of plugins (portability baggage)?
Eg.
My local folder's vimrc file is named "_gvimrc" (on purpose). This reduces the hope for people like phen from amusing himself at our expense. :-)
In my $VIM/.vimrc file, I inserted:
if filereadable("_gvimrc")
source _gvimrc
endif
at the end.
I use "filereadable()" over "fileexists()" as the later has some quirkiness when tortured with opening multiple (10+) files simultaneously, (not sure why).
Of course, you can give your own unique filename to obfuscate potential trouble-makers further. Such as "_mygvimrc", "_gobbledygook", etc. You just need to settle on one standardized name and source it accordingly in your $VIM/.vimrc. Relying on vi/vim internals for this rules out portability issues. BUT, DO NOT name it .vimrc (or _vimrc) to prevent recursive sourcing in case you're editing the $VIM/.vimrc file with vim later.
Been using this since Windoze 98SE, through Windork XP Pro, and now Windorkier 7 (5+ years already). I'll mark a list of .txt files in Explorer and then use "Edit with multiple Vim", resulting in multiple vim windows opening simultaneously. For my work, I do this several times a day, daily. All files got treated with what I set in my local _gvimrc.

Use "editorconfig"
If the kinds of coding standards you would like to enforce 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.

Assuming people aren't adding files every few days, you can probably add a modeline at the top of each file. In fact, if your version control system allows it, you could probably enforce a rule that says that each file must have a modeline when it's checked in.

I agree with the plugin approach for security reasons.
There is a very good plugin which has not been mentioned yet. It lets you use a .lvimrc in your project directories.
Try "localvimrc" out:
http://www.vim.org/scripts/script.php?script_id=441
https://github.com/embear/vim-localvimrc

Try vim-localrc
~/
|- .local.vimrc (1)
`- project/
|- .local.vimrc (2)
`- src/
|- .local.vimrc (3)
`- main.c
https://github.com/thinca/vim-localrc/blob/master/doc/localrc.txt

I looked at the plugins that existed and didn't really fancy any of them, so I wrote a simple function that piggy backs on vim-fugitive. The advantage of this is that it knows the root of the project is always the root of the repository, and additionally I can hash the file to keep a trust table. Just put the following in your .vimrc file.
function LoadRepoVimrc()
let l:path = fugitive#repo().tree('.vimrc')
if filereadable(l:path)
let l:sha1 = fugitive#repo().git_chomp('hash-object',l:path)
if !exists('g:SAFE_VIMRC') | let g:SAFE_VIMRC = {} | endif
if has_key(g:SAFE_VIMRC,l:path) && g:SAFE_VIMRC[l:path] ==? l:sha1
execute 'source '.fnameescape(l:path)
elseif confirm("Trust ".l:path."?", "&Yes\n&No",2) == 1
let g:SAFE_VIMRC[l:path] = l:sha1
execute 'source '.fnameescape(l:path)
else
execute 'sandbox source '.fnameescape(l:path)
endif
endif
endfunction
autocmd User FugitiveBoot call LoadRepoVimrc()
set viminfo ^= !
If the ! option is set on the viminfo setting, then the SAFE_VIMRC dictionary will be preserved between runs (note the ^ to prepend the option so it doesn't mess up the n option).

Related

How to organize content .vimrc in multiple files

Is there any methodology to organize the content of .vimrc in multiple files?
Currently my .vimrc has everything: Plugs statement, remaps, sets,functions,mapleader, custom plugins configuration, autogroup, etc.
I would like to organize in multiple files, perhaps by language.
Thank you!
You could split the contents of .vimrc into different files. Then source those files from within vimrc. Example:
" File: vimrc
" Author: Jonh Doe
" Options, commands, and auto commands
runtime settings.vim
" Maps
runtime maps.vim
" Functions
runtime functions.vim
" Plugin settings
runtime plug-settings.vim
Filetype-specific settings should be stored under ~/.vim/ftplugin, or less commonly, under ~/.vim/after/ftplugin. For example, html settings should be in ~/.vim/ftplugin/html.vim.
I suggest to take a look at vimrcs of experienced vim users. This repository should be a good starting point.
After your ~/.vimrc, Vim starts sourcing the plugin/ scripts. For your own mappings and custom commands, you can just place them anywhere in there, e.g. ~/.vim/plugin/MySuperCommand.vim and ~/.vim/plugin/MyLifeSaverMappings.vim.
For customization of other plugins, or Vim options that influence the behavior of plugins, it is crucial that these execute before the plugin(s). By using the ~/.vimrc (the general recommendation), this is ensured automatically. You can explicitly :runtime the scripts from your ~/.vimrc, as per #Sergio's answer, or define them as plugin scripts, too, but ensure that they run first:
If you install plugins the traditional way (in ~/.vim/plugin/), you can use the script naming (e.g. 00MyStuff.vim) to influence loading order.
If you use pack plugins, or a package manager, just ensure that your own plugin directory comes first in the 'runtimepath'.
The :scriptnames command is a valuable troubleshooting tool to verify that the script loading order is correct.

Which commands are needed to set at top of the .vimrc file?

My question is pretty clear in title, isn't it?
Actually I'm writing my .vimrc and I want to know which commands should be set at the top of a .vimrc file? (like :set nocp that it needs be be first in a .vimrc file (according to its help file))
Personally, I have set nocompatible, then Vundle stuff (according to its docs), then just sets in alphabetic order and other commands. (By the way, 1928 lines that accumulated in my .vimrc over years work pretty well even after resourcing without any particular effort for that. I use indentation for sections, subsections, etc. to keep the config manageable.)
There are no mandatory commands, since if something must always be done for everyone, then this is not a part of a config.
In general, just write what you need step-by-step and fix any incompatibilities when they show up.
No, set nocompatible is not necessary anywhere in your vimrc.
I've collected a number of battle-tested best practices in this repository.

Vim hard or soft tab depending on what's used in the file

Is there a vim command or plugin that will span the source file I'm opening, and adjust my tab setting to whatever is used in the file.
I currently work on a diverse codebase at work, with some source files using hard tabs, other 4 space soft tabs, and other's 2 space soft tabs. My hard tab, if I forgot to changes, can lead to ugly whitespace in different editors if I forget to change it when I'm editting a soft tab file.
I'd like to not have to remember to check whatever's convention is used in a file every time I open a buffer, and adjust my preferences accordingly.
I use yaifa with great success. It's pretty much an "install-and-forget" plugin that does what it says it does without ever getting in the way. Working in the messy environment I work in was horrible until I found that gem.
If most people at work use Vim (and/or Emacs), you can encode the indent settings within the file itself, see :help modeline (at least Emacs has something similar). Of course, agreeing on a common setting and gradually migrating to it would be even better :-)
In case you can't do that or things are just too chaotic, you need a plugin to dynamically adapt the indent settings. My IndentConsistencyCop plugin checks whether the buffer's indentation is consistent and conforms to tab settings, and then offers to adapt the settings to the detected ones. (The plugin page has links to alternative plugins.)
I've used the following function (found it somewhere on the web) with good success. Just put it into your .vimrc:
function Kees_settabs()
if len(filter(getbufline(winbufnr(0), 1, "$"), 'v:val =~ "^\\t"')) > len(filter(getbufline(winbufnr(0), 1, "$"), 'v:val =~ "^ "'))
set noet
else
set et
endif
endfunction
autocmd BufReadPost * call Kees_settabs()
Take a look at sleuth by the prolific Tim Pope:
This plugin 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. In lieu of adjusting 'softtabstop', 'smarttab' is enabled.
I wrote this because I wanted something fully automatic. My goal is that by installing this plugin, you can remove all indenting related configuration from your vimrc.
If your file is consistently indented with hard tabs, 'shiftwidth' will be set to your 'tabstop'. Otherwise, a 'tabstop' of 8 is enforced.

howto change location of .vimrc and .vim

How can I change the location of the .vim folder and the .vimrc file so that I can use two (or more) independent versions of vim? Is there a way to configure that while compiling vim from source? (maybe an entry in the feature.h?)
Why do I want to do such a thing?:
I have to work on project that use python2 as well as python3, therefore I want to have two independent vim setups with different plugins, configurations etc. Moreover, one version has to be compiled with +python, the other with +python3.
You can influence which ~/.vimrc is used via the -u vimrc-file command-line argument. Since this is the first initialization, you can then influence from where plugins are loaded (i.e. the .vim location) by modifying 'runtimepath' in there.
Note that for editing Python files of different versions, those settings (like indent, completion sources, etc.) are taken from filetype plugins which are sourced for every buffer separately, so it should be possible to even edit both Python 2 and 3 in the same Vim instance. (Unless you have some badly written plugins that define global stuff.) So for that, some sort of per-buffer configuration (some :autocmds on the project path, or some more elaborate solution (search for localrc plugins or questions about project vimrc here) might suffice already.
Also note that when the Python interpreter (which you'd only need for Python-based plugins and some interactive :py commands, not for editing Python) is compiled in with dynamic linking (which is the default at least on Windows), you can have both Python 2 and 3 support in the same Vim binary.
I think the easiest solution would be just to let pathogen handle your runtimepath for you.
pathogen#infect() can take paths that specify different directories that you can use for your bundle directory.
So if your .vim directory would look like this
.vim/
autoload/
pathogen.vim
bundle_python2/
<plugins>
bundle_python3/
<other plugins>
Then inside one of your vimrc for python 2 specific stuff you would have
call pathogen#infect('bundle_python2/{}')
and for python 3 specific stuff you would have
call pathogen#infect('bundle_python3/{}')
Since each plugin folder is really just a .vim folder you can place your python specific configuration stuff in a folder of the corresponding bundle and pretend its a .vim.
This structure also has the added benefit that you can change both configurations at the same time if you feel like it by putting common stuff in .vim normally.
You can also pass multiple bundle directories if you feel like to pathogen so you can have plugins that are shared without duplicating files. You just do this by passing multiple paths to pathogen#infect('bundle/{}', 'bundle_python3/{}')
After this is all done you can just create aliases for vim to call the correct vimrc file.
I found a way to do this!
You can just create a fake $HOME, whose contents are simply the .vim folder and .vimrc. Then, when running vim, set the HOME environment variable to that folder, and change it back on VimEnter.
Run vim with:
OLD_HOME="$HOME" HOME="$FAKE_HOME" vim
Add this to your .vimrc:
autocmd VimEnter * let $HOME = $OLD_HOME
On Windows you can use
let $HOME = $HOMEDRIVE.$HOMEPATH
insetead, no need to store the old home.
This works, but if you use $HOME inside your vimrc or any plugins will see the old value, it might affect them somehow. So far I haven't seen it.
Note: I don't really recommend doing this.
If you really really want to recompile vim so that it uses a different vimrc and different configuration directory take a look at src/feature.h
Search this file for USR_VIMRC_FILE. Uncomment it and place the name of your vimrc here. This will change the defualt vimrc file.
So it should look something like this
#define USR_VIMRC_FILE "~/path/to/vimrc"
Inside src/os_unix.h or src/os_mac.h and search for DFLT_RUNTIMEPATH. Change all instance of ~/.vim to whatever folder you want. This should set the default runtime path that vim searches for settings.

How can I achieve project specific indentation in vim?

I'm working on several projects, each of which uses different indentation style (for various filetypes). For example 1 tab per indentation level, 2 or 4 spaces etc. How can I automate switching between these different styles? I normaly prefer indenting with tabs, but I'm tired of having to type :set expandtabs all the time when working with space-indented code. Possible solutions would include loading a piece of vim configuration based on file path or some configuration in the project root. Is there a plugin to solve this for me in an elegant way?
Look at the cinoptions option and softtabstop option (and expandtab, but you know that).
In your '~/.vimrc', define buffer entry auto-commands for each directory where you keep sources of some project like:
augroup ProjectSetup
au BufRead,BufEnter /path/to/project1/* set et sts=2 cindent cinoptions=...
au BufRead,BufEnter /path/to/project2/* set noet sts=4 cindent cinoptions=...
augroup END
If the project has mixture of languages and needs different settings for then, you can also
add extensions like:
au BufRead,BufEnter /path/to/project1/*.{c,h} set noet sts=0 cindent cinoptions=...
au BufRead,BufEnter /path/to/project1/*.py set et sts=4
I use the plugin localvimrc, which does exactly what you are asking for:
Sometimes, when you work on different projects, you have the problem, that they use different indentation, tab expansion and so on. You need vimrc for each project that overrides your prefered settings from ~/.vimrc
EditorConfig and it's Vim plugin:
What is EditorConfig?
EditorConfig helps developers define and maintain consistent coding
styles between different editors and IDEs. The EditorConfig project
consists of a file format for defining coding styles and a collection
of text editor plugins that enable editors to read the file format and
adhere to defined styles. EditorConfig files are easily readable and
they work nicely with version control systems.
Among few other things it allows you to set indentation, which will be applied only for this project. It's very simple and most importantly standardized way supported by many different editors and IDE-s, so that it will set the proper indentation not only for you but likely all people working on a project.
You just need to create a .editorconfig file in the project root and Vim automatically finds it (assuming you have the plugin installed), setting the proper values. Creating .editorconfig files for each project achieves what you need - project specific indentation.
Example config file:
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.{js,html}]
indent_size = 2
[*.css]
indent_size = 4
Yes, there is: If you're using the Project Plugin, you could specify a file whose content is being evaluated every time you open a file of the project (this file is called in.vim). The opposite of in.vim is out.vim: this one's executed every time you leave the project.
For everything that Editorconfig supports, the right answer is to use it, see the separate answer for that.
For other settings though, you could use .vimrc files with set exrc secure.
See :h exrc:
d. 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 and OS/2) (*)
"_vimrc" (for MS-DOS and Win32) (*)
- The file "_vimrc" (for Unix, Amiga and OS/2) (*)
".vimrc" (for MS-DOS and Win32) (*)
- The file ".exrc" (for Unix, Amiga and OS/2)
"_exrc" (for MS-DOS and Win32)
See :h secure:
When on, ":autocmd", shell and write commands are not allowed in
".vimrc" 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 ".vimrc" 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 ~/.vimrc then.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.

Resources