How can I achieve project specific indentation in vim? - 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.

Related

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.

How do you set up formatting in vim?

Earlier, when I used open .py files in vim on ubuntu, they would be well formatted, with separate colours for separate segments of the program. Now, when I am using VIM on ubuntu, all the text in the .py file appears black. How can I correct this?
Formating in Vim means text formatting; e.g. indenting lists and breaking long lines. You're concerned about syntax highlighting, which is purely about the visual appearance of code.
First, it needs to be turned on.
:syntax on
does that.
Second, you probably want Vim to automatically detect the used language (e.g. Python) and choose the correct syntax plugin for you.
:filetype on
does that, though you usually enable more via :filetype plugin indent on.
To make these settings persistent, put them into your ~/.vimrc configuration.
Check man vim. In a nutshell, find a copy of a vimrc file, one might be under /usr/share/vim/ subtree. It may be named vimrc_example.vim. Copy to your home directory and rename it as .vimrc.

Quickest Way to Revert Spaces to TABs in VIM

I have always been one to replace TABs in VIM with x amount of spaces (usually 4).
Four lines I almost always use in my .vimrc config file are:
set tabstop=4
set shiftwidth=4
set expandtab
syntax on
Basically, there are moments when I NEED to use a single TAB (such as Makefiles), and I don't know how else to work around that other than leaving the file, editing my .vimrc, and then reloading the file of interest.
That said, what is the quickest way (from within VIM) to revert it back to using TABS, and then reverting back to my original settings? I'm looking for the least-hassle, least-keystrokes solution.
VIM will automatically enable the TAB for a makefile, assuming you name it "makefile," as opposed to "Makefile." Not sure why VIM still doesn't detect the type with a lower-uppercase difference, but such is life. (#Sedrik)
That aside, other alternative solutions are:
Filetype Binding (#ThorstenS #tungd):
autocmd FileType make setlocal noexpandtab
RealTime Switch (#ThorstenS):
Assuming the .vimrc configuration mentioned in the question, do:
:set noet (to switch from spaces to TAB)
and :set et (to switch back)
Just use the magical escape key available in insert mode.
On the *NIX's it is ^V by default when you are in insert mode. On Windows, you need to find out what the magical escape character is - ^V is taken for something else; I think it may be ^Q or ^S?
So! In your makefile:
this: this.c
<C-V><Tab>cc this.c
where the usual meanings apply:
means hit ctrl-V (you should see a ^ hiding away under the cursor)
- hit the tab key. Bingo.
Works for me.
Note: if you use vim settings or startup code which smashes tabs as you read a file, this obviously is a short-term fix. I prefer to learn how to use the retab command to ensure a file is tab-clean, because I don't like a file to be touched unless I consciously choose to do so.
Just type set noexpandtab . Perhaps you bind this to a function key.
Only this configuration helped me solve this problem.
filetype plugin indent on
filetype detect
autocmd FileType make set noexpandtab
Vim defaults to tabstop=8 and noexpandtab, so the defaults are well suited to working with Makefiles. If your .vimrc uses custom options for tabstop, expandtab, etc., one simple solution is to bypass your .vimrc while working with Makefiles.
From the manpage (emphasis mine):
-u {vimrc} Use the commands in the file {vimrc} for initializations. All the other initializations are skipped. Use this to edit a special kind of files. It can also be used to skip all initializations by giving the name "NONE". See ":help initialization" within vim for more details.
Since I can never remember the necessary flag/value/formatting, I've created a Bash alias which remembers for me: alias vimnone='vim -u NONE'
You can create a custom configuration per file type.
mkdir -p ~/.vim/after/indent
echo 'set noexpandtab' >> ~/.vim/after/indent/make.vim
Basically, here we created a new indent configuration for makefiles that will be loaded after other scripts.
source

Vim - indent like Emacs

I use vim (primary so that I can work on plain ssh terminal - still uncomfortable with Emacs non-gui version) but most of my colleagues in the organization use emacs. So using CVS, we face indentation inconsistency issues (tabs becoming spaces, number of tabs/spaces, code layout etc).
Is there a way I can make VIM indent EXACTLY as EMACS. (similar to the default emacs profile my colleagues use).
(Most importantly, I want vim's C++ and TCL indentation schemes to match that of emacs).
regards,
JP
I don't know if there's a way to directly import Emacs indentation settings into vim, but you can probably configure the same behavior in vim itself:
set expandtab will convert tabs to spaces
set autoindent will keep indentation level from previous line
set shiftwidth=4 will affect block indentation with >> and <<
set softtabstop=4 sets the length of soft tab in spaces
set tabstop=8 sets the width of tab character
This is properly explained in vim wiki.
When you need filetype-specific indentation you have two options:
Set autocmd to change indentation on file read and file creation:
au BufRead,BufNewFile *.py,*pyw,*.html,*.js set shiftwidth=4 will set shiftwidth for *.py files.
Configure filetype plugin, create name.vim scripts inside .vim/ftplugin folder for specific file types and set the described variables there. This is also described in proper detail in vim wiki.
Regarding specialized indenting for c++ and TCL there is some special stuff that applies in aditon to all the other setting info that's been suggested. Vim has special indenting rules defined in code for different languages. Some of this is found is found in the /indent directory of the vim installation, where there is a separate file for each filetype. For more information on how this works read the help for 'indentexpr'.
The c indenting -- and I think also the indenting for c++ -- is mostly defined in Vim source-code, and has a zillion options that you can set, plus is specially configurable in c.vim or c++.vim indent file. Read help for 'cindent' and 'c-indenting' for more help on that.
In short, the tcl.vim file controls special indenting for tcl files. If you want to revise how indenting works with tcl you would want to alter the main function in that file. The c/c++ indenting is largely controlled by Vim internals but with lots of different option flags. You can control c/c++ indenting by configuring the options the way you want them and/or by writing a function for the indent file in /indent directory. (I believe there is no c++ file in /indent directory, not sure if c.vim is file to edit there, or whether you need to create new c++.vim file. I think it's the c.vim file that would be used. which is basically an empty shell in standard Vim install, but you can read other *.vim indent files to get the idea of how they work.
Here's as extract of some options concerning indentation from .vimrc:
set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set smartindent
All options are nicely described in vim help:
:help smartindent
:help autoindent
UPD: also for C-like languages you may consider :help C-indenting

Vim: apply settings on files in directory

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).

Resources