[file] Changing Vim indentation behavior by file type

Could someone explain to me in simple terms the easiest way to change the indentation behavior of Vim based on the file type? For instance, if I open a Python file it should indent with 2 spaces, but if I open a Powershell script it should use 4 spaces.

This question is related to file vim settings indentation

The answer is


Today, you could try editorconfig, there is also a vim plugin for it. With this, you are able not only change indentation size in vim, but in many other editors, keep consistent coding styles.

Below is a simple editorconfig, as you can see, the python files will have 4 spaces for indentation, and pug template files will only have 2.

# 4 space indentation for python files
[*.py]
indent_style = space
indent_size = 4

# 2 space indentation for pug templates
[*.pug]
indent_size = 2

Put autocmd commands based on the file suffix in your ~/.vimrc

autocmd BufRead,BufNewFile   *.c,*.h,*.java set noic cin noexpandtab
autocmd BufRead,BufNewFile   *.pl syntax on

The commands you're looking for are probably ts= and sw=


edit your ~/.vimrc, and add different file types for different indents,e.g. I want html/rb indent for 2 spaces, and js/coffee files indent for 4 spaces:

" by default, the indent is 2 spaces. 
set shiftwidth=2
set softtabstop=2
set tabstop=2

" for html/rb files, 2 spaces
autocmd Filetype html setlocal ts=2 sw=2 expandtab
autocmd Filetype ruby setlocal ts=2 sw=2 expandtab

" for js/coffee/jade files, 4 spaces
autocmd Filetype javascript setlocal ts=4 sw=4 sts=0 expandtab
autocmd Filetype coffeescript setlocal ts=4 sw=4 sts=0 expandtab
autocmd Filetype jade setlocal ts=4 sw=4 sts=0 expandtab

refer to: Setting Vim whitespace preferences by filetype


This might be known by most of us, but anyway (I was puzzled my first time): Doing :set et (:set expandtabs) does not change the tabs already existing in the file, one has to do :retab. For example:

:set et
:retab

and the tabs in the file are replaced by enough spaces. To have tabs back simply do:

:set noet
:retab

For those using autocmd, it is a best practice to group those together. If a grouping is related to file-type detection, you might have something like this:

augroup filetype_c
    autocmd!
    :autocmd FileType c setlocal tabstop=2 shiftwidth=2 softtabstop=2 expandtab
    :autocmd FileType c nnoremap <buffer> <localleader>c I/*<space><esc><s-a><space>*/<esc>
augroup end

Groupings help keep the .vimrc organized especially once a filetype has multiple rules associated with it. In the above example, a comment shortcut specific to .c files is defined.

The initial call to autocmd! tells vim to delete any previously defined autocommands in said grouping. This will prevent duplicate definition if .vimrc is sourced again. See the :help augroup for more info.


I usually work with expandtab set, but that's bad for makefiles. I recently added:

:autocmd FileType make set noexpandtab

to the end of my .vimrc file and it recognizes Makefile, makefile, and *.mk as makefiles and does not expand tabs. Presumably, you can extend this.


Use ftplugins or autocommands to set options.

ftplugin

In ~/.vim/ftplugin/python.vim:

setlocal shiftwidth=2 softtabstop=2 expandtab

And don't forget to turn them on in ~/.vimrc:

filetype plugin indent on

(:h ftplugin for more information)

autocommand

In ~/.vimrc:

autocmd FileType python setlocal shiftwidth=2 softtabstop=2 expandtab

You can replace any of the long commands or settings with their short versions:
autocmd: au
setlocal: setl
shiftwidth: sw
tabstop: ts
softtabstop: sts
expandtab: et

I would also suggest learning the difference between tabstop and softtabstop. A lot of people don't know about softtabstop.


I use a utility that I wrote in C called autotab. It analyzes the first few thousand lines of a file which you load and determines values for the Vim parameters shiftwidth, tabstop and expandtab.

This is compiled using, for instance, gcc -O autotab.c -o autotab. Instructions for integrating with Vim are in the comment header at the top.

Autotab is fairly clever, but can get confused from time to time, in particular by that have been inconsistently maintained using different indentation styles.

If a file evidently uses tabs, or a combination of tabs and spaces, for indentation, Autotab will figure out what tab size is being used by considering factors like alignment of internal elements across successive lines, such as comments.

It works for a variety of programming languages, and is forgiving for "out of band" elements which do not obey indentation increments, such as C preprocessing directives, C statement labels, not to mention the obvious blank lines.


Personally, I use these settings in .vimrc:

autocmd FileType python set tabstop=8|set shiftwidth=2|set expandtab
autocmd FileType ruby set tabstop=8|set shiftwidth=2|set expandtab

While you can configure Vim's indentation just fine using the indent plugin or manually using the settings, I recommend using a python script called Vindect that automatically sets the relevant settings for you when you open a python file. Use this tip to make using Vindect even more effective. When I first started editing python files created by others with various indentation styles (tab vs space and number of spaces), it was incredibly frustrating. But Vindect along with this indent file

Also recommend:


Examples related to file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats?

Examples related to vim

Why does using from __future__ import print_function breaks Python2-style print? How to run vi on docker container? How can I install MacVim on OS X? Find and replace strings in vim on multiple lines Running Python code in Vim How do I set the default font size in Vim? Move cursor to end of file in vim Set encoding and fileencoding to utf-8 in Vim How to select all and copy in vim? Why I've got no crontab entry on OS X when using vim?

Examples related to settings

How to configure "Shorten command line" method for whole project in IntelliJ Error: Module not specified (IntelliJ IDEA) Instant run in Android Studio 2.0 (how to turn off) How do I open phone settings when a button is clicked? Google Chrome: This setting is enforced by your administrator maven command line how to point to a specific settings.xml for a single command? Django: ImproperlyConfigured: The SECRET_KEY setting must not be empty Python: How would you save a simple settings/config file? How to set my phpmyadmin user session to not time out so quickly? Setting DEBUG = False causes 500 Error

Examples related to indentation

How to indent/format a selection of code in Visual Studio Code with Ctrl + Shift + F Python IndentationError unindent does not match any outer indentation level How to change indentation mode in Atom? How to set HTML Auto Indent format on Sublime Text 3? "Expected an indented block" error? Indent starting from the second line of a paragraph with CSS Indentation Error in Python How to fix/convert space indentation in Sublime Text? How to make the tab character 4 spaces instead of 8 spaces in nano? IndentationError: unexpected unindent WHY?